feat(heap): Add feature to get peak heap usage

This feature keeps track of the per task peak memory usage.

- Update the heap_task_tracking example to make use of the new feature
Cleanup the implementation:
- multi_heap_get_free_size() is never used, remove it.
- Minor update in heap_caps_update_per_task_info_xx() funcitons.
- Update settting on block owner in heap_caps.c to work with the
get peak usage feature.

- Update heap_caps_update_per_task_info_free() to detect when it
is called to delete the memory allocated for a task TCB. Mark
the corresponding task in the statistic list as deleted.

- Add a Kconfig option dependant on HEAP_TASK_TRACKING being enabled
that force the deletion of the statistics related to deleted task
when set to true.

- In task tracking feature, add a current and peak memory usage
to the heap_stat_t structure to keep track of the current and
peak memory usage of the given task across all heaps.

- Fix missing block owner when allocating memory for heaps_array
in heap_caps_init.

- Keep the original implementation of the task tracking
for backward compatibility reasons.
This commit is contained in:
Guillaume Souchere
2025-02-14 08:47:29 +01:00
parent 47df2ed524
commit daf8f9edb6
16 changed files with 1368 additions and 75 deletions

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -12,6 +12,7 @@
#include "multi_heap.h"
#include "multi_heap_platform.h"
#include "esp_heap_caps_init.h"
#include "esp_heap_task_info_internal.h"
#include "heap_memory_layout.h"
#include "esp_private/startup_internal.h"
@@ -144,6 +145,10 @@ void heap_caps_init(void)
heap_idx++;
assert(heap_idx <= num_heaps);
// add the name of the newly created heap to match the region name in which it will be created
#if CONFIG_HEAP_TASK_TRACKING
heap->name = type->name;
#endif // CONFIG_HEAP_TASK_TRACKING
memcpy(heap->caps, type->caps, sizeof(heap->caps));
heap->start = region->start;
heap->end = region->start + region->size;
@@ -168,13 +173,15 @@ void heap_caps_init(void)
assert(SLIST_EMPTY(&registered_heaps));
heap_t *heaps_array = NULL;
heap_t *used_heap = NULL;
for (size_t i = 0; i < num_heaps; i++) {
if (heap_caps_match(&temp_heaps[i], MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL)) {
used_heap = temp_heaps + i;
if (heap_caps_match(used_heap, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL)) {
/* use the first DRAM heap which can fit the data.
* the allocated block won't include the block owner bytes since this operation
* is done by the top level API heap_caps_malloc(). So we need to add it manually
* after successful allocation. Allocate extra 4 bytes for that purpose. */
heaps_array = multi_heap_malloc(temp_heaps[i].heap, MULTI_HEAP_ADD_BLOCK_OWNER_SIZE(sizeof(heap_t) * num_heaps));
heaps_array = multi_heap_malloc(used_heap->heap, MULTI_HEAP_ADD_BLOCK_OWNER_SIZE(sizeof(heap_t) * num_heaps));
if (heaps_array != NULL) {
break;
}
@@ -199,6 +206,13 @@ void heap_caps_init(void)
* until the smaller heaps are full. */
sorted_add_to_registered_heaps(&heaps_array[i]);
}
#if CONFIG_HEAP_TASK_TRACKING
heap_caps_update_per_task_info_alloc(used_heap,
MULTI_HEAP_REMOVE_BLOCK_OWNER_OFFSET(heaps_array),
multi_heap_get_full_block_size(used_heap->heap, MULTI_HEAP_REMOVE_BLOCK_OWNER_OFFSET(heaps_array)),
get_all_caps(used_heap));
#endif
}
esp_err_t heap_caps_add_region(intptr_t start, intptr_t end)
@@ -279,6 +293,15 @@ esp_err_t heap_caps_add_region_with_caps(const uint32_t caps[], intptr_t start,
err = ESP_ERR_NO_MEM;
goto done;
}
#if CONFIG_HEAP_TASK_TRACKING
// add the name of the newly created heap to match the region name in which it will be created
for(size_t i = 0; i < soc_memory_type_count; i++) {
if (get_ored_caps(caps) == get_ored_caps(soc_memory_types[i].caps)) {
p_new->name = soc_memory_types[i].name;
break;
}
}
#endif // CONFIG_HEAP_TASK_TRACKING
memcpy(p_new->caps, caps, sizeof(p_new->caps));
p_new->start = start;
p_new->end = end;