feat(examples): Update heap task tracking examples

update example to showcasee the new API of heap task tracking

- Add basic heap task traacking example
- Add advanced example for task tracking
This commit is contained in:
Guillaume Souchere
2025-02-14 08:49:38 +01:00
parent daf8f9edb6
commit d429b1fdbb
16 changed files with 651 additions and 140 deletions

View File

@@ -0,0 +1,8 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
idf_build_set_property(MINIMAL_BUILD ON)
project(basic)

View File

@@ -0,0 +1,156 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- |
# Heap Task Tracking Basic Example
## Overview
The example creates a task which allocates random amount of memory and frees it and another task that allocates random amount of memory but never frees it.
The main then goes into a loop printing the overview information of each task that allocated memory dynamically.
The information include:
- The task name
- The task status
- The current memory usage
- The peak memory usage
- The number of heaps currently used by the task
Because the heap task tracking feature requires additional metadata to be allocated for each memory allocations, the overall heap usage of the application is
greater than when the feature is disabled. For this reason, it is highly recommended to use the task tracking for debugging purpose only.
### Configure the project
- Enable thee option `Enable heap task tracking` by opening the project configuration menu (`idf.py menuconfig`) and navigate to `Component config -> Heap memory debugging` menu.
- (optional) Enable the option `Keep information about the memory usage on deleted tasks` if you wish to keep track of the information of a task after it has been deleted.
### Build and Flash
Run `idf.py -p PORT flash monitor` to build and flash the project..
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
## Example Output
```
Starting task: no_leak_task
Starting task: leaking_task
PRINTING OVERVIEW STATISTICS OF EACH TASK
┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐
│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │
├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤
│ leaking_task │ ALIVE │ 6656 │ 8064 │ 1 │
│ no_leak_task │ ALIVE │ 0 │ 7152 │ 1 │
│ main │ ALIVE │ 7412 │ 7412 │ 2 │
│ ipc1 │ ALIVE │ 32 │ 44 │ 1 │
│ ipc0 │ ALIVE │ 10080 │ 10092 │ 1 │
│ Pre-scheduler │ ALIVE │ 2236 │ 2236 │ 1 │
└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘
PRINTING OVERVIEW STATISTICS OF NO LEAK TASK
┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐
│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │
├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤
│ no_leak_task │ ALIVE │ 0 │ 7152 │ 1 │
└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘
PRINTING OVERVIEW STATISTICS OF LEAKING TASK
┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐
│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │
├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤
│ leaking_task │ ALIVE │ 6656 │ 8064 │ 1 │
└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘
[...]
Deleting task: leaking_task
PRINTING OVERVIEW STATISTICS OF EACH TASK
┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐
│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │
├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤
│ leaking_task │ DELETED │ 11392 │ 11616 │ 1 │
│ no_leak_task │ ALIVE │ 0 │ 9408 │ 2 │
│ main │ ALIVE │ 3860 │ 7412 │ 2 │
│ ipc1 │ ALIVE │ 32 │ 44 │ 1 │
│ ipc0 │ ALIVE │ 10080 │ 10092 │ 1 │
│ Pre-scheduler │ ALIVE │ 2236 │ 2236 │ 1 │
└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘
PRINTING OVERVIEW STATISTICS OF NO LEAK TASK
┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐
│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │
├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤
│ no_leak_task │ ALIVE │ 0 │ 9408 │ 2 │
└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘
PRINTING OVERVIEW STATISTICS OF LEAKING TASK
┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐
│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │
├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤
│ leaking_task │ DELETED │ 11392 │ 11616 │ 1 │
└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘
Deleting task: no_leak_task
PRINTING OVERVIEW STATISTICS OF EACH TASK
┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐
│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │
├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤
│ leaking_task │ DELETED │ 11392 │ 11616 │ 1 │
│ no_leak_task │ DELETED │ 0 │ 9408 │ 2 │
│ main │ ALIVE │ 308 │ 7412 │ 2 │
│ ipc1 │ ALIVE │ 32 │ 44 │ 1 │
│ ipc0 │ ALIVE │ 10080 │ 10092 │ 1 │
│ Pre-scheduler │ ALIVE │ 2236 │ 2236 │ 1 │
└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘
PRINTING DETAILED STATISTICS OF EACH TASK
├ DELETED: leaking_task, CURRENT MEMORY USAGE 11392, PEAK MEMORY USAGE 11616, TOTAL HEAP USED 1:
│ └ HEAP: RAM, CAPS: 0x0010580e, SIZE: 22308, USAGE: CURRENT 11392 (51%), PEAK 11616 (52%), ALLOC COUNT: 3
│ ├ ALLOC 0x3fcebbb8, SIZE 6656
│ ├ ALLOC 0x3fced5bc, SIZE 3584
│ ├ ALLOC 0x3fceb718, SIZE 1152
├ DELETED: no_leak_task, CURRENT MEMORY USAGE 0, PEAK MEMORY USAGE 9408, TOTAL HEAP USED 2:
│ ├ HEAP: RAM, CAPS: 0x0010580e, SIZE: 22308, USAGE: CURRENT 0 (0%), PEAK 7152 (32%), ALLOC COUNT: 0
│ └ HEAP: RAM, CAPS: 0x0010580e, SIZE: 344400, USAGE: CURRENT 0 (0%), PEAK 9216 (2%), ALLOC COUNT: 0
├ ALIVE: main, CURRENT MEMORY USAGE 308, PEAK MEMORY USAGE 7412, TOTAL HEAP USED 2:
│ ├ HEAP: RAM, CAPS: 0x0010580e, SIZE: 344400, USAGE: CURRENT 220 (0%), PEAK 220 (0%), ALLOC COUNT: 2
│ │ ├ ALLOC 0x3fc99024, SIZE 88
│ │ ├ ALLOC 0x3fc99124, SIZE 132
│ └ HEAP: RAM, CAPS: 0x0010580e, SIZE: 22308, USAGE: CURRENT 88 (0%), PEAK 7192 (32%), ALLOC COUNT: 5
│ ├ ALLOC 0x3fce99f8, SIZE 20
│ ├ ALLOC 0x3fce9a10, SIZE 12
│ ├ ALLOC 0x3fce9a20, SIZE 16
│ ├ ALLOC 0x3fce9a34, SIZE 20
│ ├ ALLOC 0x3fce9a4c, SIZE 20
├ ALIVE: ipc1, CURRENT MEMORY USAGE 32, PEAK MEMORY USAGE 44, TOTAL HEAP USED 1:
│ └ HEAP: RAM, CAPS: 0x0010580e, SIZE: 344400, USAGE: CURRENT 32 (0%), PEAK 44 (0%), ALLOC COUNT: 2
│ ├ ALLOC 0x3fc990fc, SIZE 16
│ ├ ALLOC 0x3fc991c0, SIZE 16
├ ALIVE: ipc0, CURRENT MEMORY USAGE 10080, PEAK MEMORY USAGE 10092, TOTAL HEAP USED 1:
│ └ HEAP: RAM, CAPS: 0x0010580e, SIZE: 344400, USAGE: CURRENT 10080 (2%), PEAK 10092 (2%), ALLOC COUNT: 10
│ ├ ALLOC 0x3fc966e0, SIZE 1312
│ ├ ALLOC 0x3fc96c80, SIZE 344
│ ├ ALLOC 0x3fc96e14, SIZE 16
│ ├ ALLOC 0x3fc96e3c, SIZE 4224
│ ├ ALLOC 0x3fc97ec0, SIZE 344
│ ├ ALLOC 0x3fc98030, SIZE 1568
│ ├ ALLOC 0x3fc98668, SIZE 344
│ ├ ALLOC 0x3fc987d8, SIZE 1568
│ ├ ALLOC 0x3fc98e10, SIZE 344
│ ├ ALLOC 0x3fc98f94, SIZE 16
└ ALIVE: Pre-scheduler, CURRENT MEMORY USAGE 2236, PEAK MEMORY USAGE 2236, TOTAL HEAP USED 1:
└ HEAP: RAM, CAPS: 0x0010580e, SIZE: 344400, USAGE: CURRENT 2236 (0%), PEAK 2236 (0%), ALLOC COUNT: 11
├ ALLOC 0x3fc95cb0, SIZE 164
├ ALLOC 0x3fc95dd8, SIZE 12
├ ALLOC 0x3fc95dfc, SIZE 12
├ ALLOC 0x3fc95e20, SIZE 16
├ ALLOC 0x3fc95e48, SIZE 24
├ ALLOC 0x3fc95e78, SIZE 88
├ ALLOC 0x3fc95ee8, SIZE 88
├ ALLOC 0x3fc95f58, SIZE 88
├ ALLOC 0x3fc95fc8, SIZE 88
├ ALLOC 0x3fc96038, SIZE 1312
├ ALLOC 0x3fc96570, SIZE 344
I (5949) main_task: Returned from app_main()
```

View File

@@ -0,0 +1,2 @@
idf_component_register(SRCS "heap_task_tracking_main.c"
INCLUDE_DIRS "")

View File

@@ -0,0 +1,117 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* Heap Task Tracking Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_heap_task_info.h"
#include "esp_heap_caps.h"
#include "esp_random.h"
#include "esp_log.h"
static void no_leak_task(void *args)
{
size_t size_a = 0;
size_t size_b = 0;
char *task_name = pcTaskGetName(*((TaskHandle_t*)args));
printf("Starting task: %s\n", task_name);
while(1) {
/* Allocate random amount of memory for demonstration */
size_a = (esp_random() % 10000) + 1;
size_b = (esp_random() % (10000 - size_a)) + 1;
void *ptr_a = heap_caps_malloc(size_a, MALLOC_CAP_DEFAULT);
void *ptr_b = heap_caps_malloc(size_b, MALLOC_CAP_DEFAULT);
if (ptr_a == NULL || ptr_b == NULL) {
ESP_LOGE(task_name, "Could not allocate heap memory");
abort();
}
heap_caps_free(ptr_a);
heap_caps_free(ptr_b);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
static void leaking_task(void *args)
{
size_t size_a = 0;
size_t size_b = 0;
char *task_name = pcTaskGetName(*((TaskHandle_t*)args));
printf("Starting task: %s\n", task_name);
while(1) {
/* Allocate random amount of memory for demonstration */
size_a = (esp_random() % 10000) + 1;
size_b = (esp_random() % (10000 - size_a)) + 1;
void *ptr_a = heap_caps_malloc(size_a, MALLOC_CAP_DEFAULT);
void *ptr_b = heap_caps_malloc(size_b, MALLOC_CAP_DEFAULT);
if (ptr_a == NULL || ptr_b == NULL) {
ESP_LOGE(task_name, "Could not allocate heap memory");
abort();
}
heap_caps_free(ptr_a);
// heap_caps_free(ptr_b);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void app_main(void)
{
TaskHandle_t no_leak_task_hdl, leaking_task_hdl;
/* Create example task to demonstrate heap_task_tracking */
xTaskCreate(&no_leak_task, "no_leak_task", 3072, &no_leak_task_hdl, 5, &no_leak_task_hdl);
xTaskCreate(&leaking_task, "leaking_task", 3072, &leaking_task_hdl, 5, &leaking_task_hdl);
/* print task statistic periodically */
for(size_t counter = 0; counter < 4; counter++) {
/* print the overview stats of every task */
printf("\n PRINTING OVERVIEW STATISTICS OF EACH TASK\n");
heap_caps_print_all_task_stat_overview(stdout);
/* print the overview statistics of the no leak task */
printf("\n PRINTING OVERVIEW STATISTICS OF NO LEAK TASK\n");
heap_caps_print_single_task_stat_overview(stdout, no_leak_task_hdl);
/* print the overview statistics of the leaking task */
printf("\n PRINTING OVERVIEW STATISTICS OF LEAKING TASK\n");
heap_caps_print_single_task_stat_overview(stdout, leaking_task_hdl);
if (counter == 2) {
/* delete the leaking task and let the no leak task run
* for some more time */
printf("Deleting task: %s\n", pcTaskGetName(leaking_task_hdl));
vTaskDelete(leaking_task_hdl);
}
/* wait for a second before running the loop again*/
vTaskDelay(pdMS_TO_TICKS(1000));
}
/* Delete the no leak task */
printf("Deleting task: %s\n", pcTaskGetName(no_leak_task_hdl));
vTaskDelete(no_leak_task_hdl);
/* print overview information of every task */
printf("\n PRINTING OVERVIEW STATISTICS OF EACH TASK\n");
heap_caps_print_all_task_stat_overview(stdout);
/* print detailed statistics for every task */
printf("\n PRINTING DETAILED STATISTICS OF EACH TASK\n");
heap_caps_print_all_task_stat(stdout);
}

View File

@@ -0,0 +1,5 @@
# enable the task tracking feature
CONFIG_HEAP_TASK_TRACKING=y
# keep task tracking information after the task is deleted
CONFIG_HEAP_TRACK_DELETED_TASKS=y