Skip to content

Commit a8c18b0

Browse files
committed
vmh: add virtual heap stats
Option that allows collecting statistics on individual allocator of a virtual memory heap. By defaults the following states are output per allocator: 1. Maximal number of blocks allocated at any given moment during the heap lifespan 2. How many times the allocator was full, and an allocation had to be redirected to another allocator (with greater/less optimal block size) By default, stats are outputted only on allocation error This feature depends on SYS_MEM_BLOCKS_RUNTIME_STATS Zephyr option and hence is controlled by the same config option Signed-off-by: Wojciech Jablonski <[email protected]>
1 parent a86f371 commit a8c18b0

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed

zephyr/include/sof/lib/regions_mm.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ int vmh_free_heap(struct vmh_heap *heap);
8787
int vmh_free(struct vmh_heap *heap, void *ptr);
8888
void vmh_get_default_heap_config(const struct sys_mm_drv_region *region,
8989
struct vmh_heap_config *cfg);
90+
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS
91+
void vmh_log_stats(struct vmh_heap *heap);
92+
#endif
9093
/**
9194
* @brief Checks if ptr is in range of given memory range
9295
*

zephyr/lib/alloc.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,12 @@ static void *virtual_heap_alloc(struct vmh_heap *heap, uint32_t flags, size_t by
290290
{
291291
void *mem = vmh_alloc(heap, bytes);
292292

293-
if (!mem)
293+
if (!mem) {
294+
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS
295+
vmh_log_stats(heap);
296+
#endif
294297
return NULL;
298+
}
295299

296300
assert(IS_ALIGNED(mem, align));
297301

zephyr/lib/regions_mm.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#if defined(CONFIG_MM_DRV)
1111
#include <sof/lib/regions_mm.h>
1212

13+
LOG_MODULE_DECLARE(mem_allocator, CONFIG_SOF_LOG_LEVEL);
1314

1415
/** @struct vmh_heap
1516
*
@@ -32,6 +33,10 @@ struct vmh_heap {
3233
const struct sys_mm_drv_region *virtual_region;
3334
struct sys_mem_blocks *physical_blocks_allocators[MAX_MEMORY_ALLOCATORS_COUNT];
3435
struct sys_bitarray *allocation_sizes[MAX_MEMORY_ALLOCATORS_COUNT];
36+
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS
37+
unsigned int out_of_blocks[MAX_MEMORY_ALLOCATORS_COUNT];
38+
bool logged;
39+
#endif
3540
bool allocating_continuously;
3641
};
3742

@@ -398,6 +403,9 @@ static void *_vmh_alloc(struct vmh_heap *heap, uint32_t alloc_size)
398403
int mem_block_iterator, allocation_error_code = -ENOMEM;
399404
size_t allocation_bitarray_offset, block_count = 0, block_size = 0,
400405
allocation_bitarray_position = 0;
406+
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS
407+
bool first_match = true;
408+
#endif
401409

402410
/* We will gather error code when allocating on physical block
403411
* allocators.
@@ -487,6 +495,11 @@ static void *_vmh_alloc(struct vmh_heap *heap, uint32_t alloc_size)
487495
sys_bitarray_set_region(heap->allocation_sizes[mem_block_iterator],
488496
block_count - 1, allocation_bitarray_position);
489497
break;
498+
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS
499+
} else if (first_match) {
500+
++heap->out_of_blocks[mem_block_iterator];
501+
first_match = false;
502+
#endif
490503
}
491504
}
492505

@@ -699,6 +712,39 @@ int vmh_free(struct vmh_heap *heap, void *ptr)
699712
return ret;
700713
}
701714

715+
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS
716+
/**
717+
* @brief Print stats on heap usage per allocator
718+
*
719+
* @param heap pointer to a heap for which statistics are collected
720+
*/
721+
void vmh_log_stats(struct vmh_heap *heap)
722+
{
723+
if (heap->logged)
724+
return;
725+
726+
LOG_INF("Virtual heap stats per allocator");
727+
LOG_INF(" ID | Total | Max use| Times run out of blocks");
728+
729+
for (int idx = 0; idx < MAX_MEMORY_ALLOCATORS_COUNT; idx++) {
730+
if (!heap->physical_blocks_allocators[idx])
731+
continue;
732+
733+
struct sys_memory_stats stats = {0};
734+
735+
sys_mem_blocks_runtime_stats_get(heap->physical_blocks_allocators[idx], &stats);
736+
737+
size_t block_size = 1 << heap->physical_blocks_allocators[idx]->info.blk_sz_shift;
738+
size_t block_num = heap->physical_blocks_allocators[idx]->info.num_blocks;
739+
740+
LOG_INF("%7d| %7u| %7u| %7u", idx, block_num,
741+
(stats.max_allocated_bytes/block_size),
742+
heap->out_of_blocks[idx]);
743+
}
744+
heap->logged = true;
745+
}
746+
#endif
747+
702748
/**
703749
* @brief Get default configuration for heap
704750
*

0 commit comments

Comments
 (0)