Skip to content

Tools: Testbench: Track and print heap usage for modules#10593

Open
singalsu wants to merge 1 commit intothesofproject:mainfrom
singalsu:testbench_print_heap_usage
Open

Tools: Testbench: Track and print heap usage for modules#10593
singalsu wants to merge 1 commit intothesofproject:mainfrom
singalsu:testbench_print_heap_usage

Conversation

@singalsu
Copy link
Collaborator

@singalsu singalsu commented Mar 3, 2026

This patch adds to end to sof-testbench4 run print of peak heap consumption for each module. The information is retrieved from heap_high_water_mark data that is tracked by module adapter for each module.

Example of output (sof-hda-generic.tplg):

Heap usage for module gain.1.1: 708 bytes
Heap usage for module mixin.1.1: 164 bytes
Heap usage for module gain.2.1: 708 bytes
Heap usage for module eqiir.2.1: 316 bytes
Heap usage for module eqfir.2.1: 388 bytes
Heap usage for module drc.2.1: 4316 bytes
Heap usage for module mixout.2.1: 252 bytes

@singalsu singalsu marked this pull request as ready for review March 3, 2026 17:08
Copilot AI review requested due to automatic review settings March 3, 2026 17:08
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds reporting of per-module peak heap consumption at the end of a sof-testbench4 run by reading each module’s heap_high_water_mark tracked by the module adapter.

Changes:

  • Collect IPC4 module heap high-water marks by iterating the IPC4 widget list and resolving component devices.
  • Print per-module heap usage in the test summary output.
  • Introduce a small record struct (tb_heap_usage_record) to pass heap usage data to the stats printer.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
tools/testbench/testbench.c Adds IPC4-only collection of module heap HWM and prints the results in the pipeline stats output.
tools/testbench/include/testbench/utils.h Introduces tb_heap_usage_record used to carry module name and heap HWM to the stats function.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

records[count].module_name = info->name;
records[count].heap_max = (int)dev->mod->priv.resources.heap_high_water_mark;
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heap_high_water_mark is a size_t (see src/include/sof/audio/module_adapter/module/generic.h), but it’s being cast to int and printed with %d. This can truncate/overflow and report incorrect (even negative) values on 64-bit hosts. Consider storing heap_max as size_t (or uint64_t) in tb_heap_usage_record and printing with the matching format specifier (e.g., %zu).

Suggested change
records[count].heap_max = (int)dev->mod->priv.resources.heap_high_water_mark;
/* heap_high_water_mark is size_t; clamp to INT_MAX to avoid overflow */
{
size_t heap_high_water_mark = dev->mod->priv.resources.heap_high_water_mark;
if (heap_high_water_mark > (size_t)INT_MAX)
records[count].heap_max = INT_MAX;
else
records[count].heap_max = (int)heap_high_water_mark;
}

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Print of %zu isn't working with xt-clang/xt-run env. I can change the storage type and typecast the print.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storage is now size_t and print is with typecast to uint32_t. We can't use more heap in DSP than what the uint32_t range is.

This patch adds to end to sof-testbench4 run print of peak
heap consumption for each module. The information is retrieved
from heap_high_water_mark data that is tracked by module adapter
for each module.

Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if (count >= TB_NUM_WIDGETS_SUPPORTED) {
fprintf(stderr, "Error: Too many components for heap records, max %d.\n",
TB_NUM_WIDGETS_SUPPORTED);
break;
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tb_collect_heap_usage() caps heap records at TB_NUM_WIDGETS_SUPPORTED (16) and breaks out, which will silently drop heap usage for remaining modules on larger topologies. Consider sizing the record buffer to the actual number of non-AIF/DAI components (e.g., first pass to count, then allocate), or introduce a dedicated "max components" constant that is large enough for real-world IPC4 topologies.

Suggested change
break;
*count_out = count;
return -EINVAL;

Copilot uses AI. Check for mistakes.
}

records[count].module_name = info->name;
records[count].heap_max = dev->mod->priv.resources.heap_high_water_mark;
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tb_collect_heap_usage() reads dev->mod->priv.resources.heap_high_water_mark directly. Since module_adapter_heap_usage(mod, &hwm) exists in the module adapter API, prefer using that accessor to avoid coupling testbench to internal processing_module layout/details.

Suggested change
records[count].heap_max = dev->mod->priv.resources.heap_high_water_mark;
if (module_adapter_heap_usage(dev->mod, &records[count].heap_max) < 0)
continue;

Copilot uses AI. Check for mistakes.
Comment on lines 458 to +460
delta_t = (td1.tv_sec - td0.tv_sec) * 1000000;
delta_t += (td1.tv_nsec - td0.tv_nsec) / 1000;
test_pipeline_stats(tp, delta_t);
test_pipeline_stats(tp, delta_t, heap_usage_records, heap_usage_records_count);
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In error paths that goto out before tb_gettime(&td0) / tb_gettime(&td1) run, td0/td1 can be uninitialized, but delta_t is still computed from them. This is undefined behavior and can print garbage timing (or worse). Initialize td0/td1 and/or gate the delta_t calculation/printing behind a flag that indicates timing was captured.

Copilot uses AI. Check for mistakes.
printf("\n");
if (delta_t)
printf("Total execution time: %lld us, %.2f x realtime\n\n", delta_t,
(float)frames_out / tp->fs_out * 1000000 / delta_t);
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_pipeline_stats() no longer prints a trailing blank line when delta_t == 0 (previously it always printed \n). If delta_t can be 0 for short runs or error cases, consider keeping an unconditional newline to avoid the next output running into the summary block.

Suggested change
(float)frames_out / tp->fs_out * 1000000 / delta_t);
(float)frames_out / tp->fs_out * 1000000 / delta_t);
else
printf("\n");

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants