From 2a5c356e177dfd86a63cefb034f03e6d6f944875 Mon Sep 17 00:00:00 2001 From: Intel Date: Thu, 20 Dec 2012 00:00:00 +0100 Subject: [PATCH] memory: stats for malloc Signed-off-by: Intel --- .../common/include/rte_malloc_heap.h | 2 + lib/librte_malloc/malloc_elem.c | 3 ++ lib/librte_malloc/malloc_elem.h | 2 +- lib/librte_malloc/malloc_heap.c | 51 +++++++++++++++++-- lib/librte_malloc/malloc_heap.h | 4 ++ lib/librte_malloc/rte_malloc.c | 35 ++++++++++++- lib/librte_malloc/rte_malloc.h | 27 ++++++++++ 7 files changed, 117 insertions(+), 7 deletions(-) diff --git a/lib/librte_eal/common/include/rte_malloc_heap.h b/lib/librte_eal/common/include/rte_malloc_heap.h index d5ea63ee04..758b4fc04d 100644 --- a/lib/librte_eal/common/include/rte_malloc_heap.h +++ b/lib/librte_eal/common/include/rte_malloc_heap.h @@ -53,6 +53,8 @@ struct malloc_heap { rte_spinlock_t lock; struct malloc_elem * volatile free_head; unsigned mz_count; + unsigned alloc_count; + size_t total_size; } __rte_cache_aligned; #endif /* _RTE_MALLOC_HEAP_H_ */ diff --git a/lib/librte_malloc/malloc_elem.c b/lib/librte_malloc/malloc_elem.c index 0d2fdb6bea..012791767a 100644 --- a/lib/librte_malloc/malloc_elem.c +++ b/lib/librte_malloc/malloc_elem.c @@ -231,7 +231,10 @@ malloc_elem_free(struct malloc_elem *elem) elem->state = ELEM_FREE; elem->pad = 0; } + /* decrease heap's count of allocated elements */ + elem->heap->alloc_count--; rte_spinlock_unlock(&(elem->heap->lock)); + return 0; } diff --git a/lib/librte_malloc/malloc_elem.h b/lib/librte_malloc/malloc_elem.h index 5c7a428578..5cd644587d 100644 --- a/lib/librte_malloc/malloc_elem.h +++ b/lib/librte_malloc/malloc_elem.h @@ -50,7 +50,7 @@ struct malloc_elem { struct malloc_elem *volatile next_free; /* to make list of free elements */ volatile enum elem_state state; uint32_t pad; - volatile size_t size; + size_t size; #ifdef RTE_LIBRTE_MALLOC_DEBUG uint64_t header_cookie; /* Cookie marking start of data */ /* trailer cookie at start + size */ diff --git a/lib/librte_malloc/malloc_heap.c b/lib/librte_malloc/malloc_heap.c index 0b350748bb..bba34dc9d0 100644 --- a/lib/librte_malloc/malloc_heap.c +++ b/lib/librte_malloc/malloc_heap.c @@ -105,6 +105,8 @@ malloc_heap_add_memzone(struct malloc_heap *heap, size_t size, unsigned align) start_elem->next_free = heap->free_head; heap->free_head = start_elem; + /* increase heap total size by size of new memzone */ + heap->total_size+=mz_size - MALLOC_ELEM_OVERHEAD; return 0; } @@ -127,6 +129,8 @@ malloc_heap_init(struct malloc_heap *heap) heap->free_head = NULL; heap->mz_count = 0; + heap->alloc_count = 0; + heap->total_size = 0; /* * Find NUMA socket of heap that is being initialised, so that * malloc_heaps[n].numa_socket == n @@ -176,15 +180,54 @@ malloc_heap_alloc(struct malloc_heap *heap, size = CACHE_LINE_ROUNDUP(size); align = CACHE_LINE_ROUNDUP(align); rte_spinlock_lock(&heap->lock); - struct malloc_elem *prev, *elem = find_suitable_element(heap, size, align, &prev); if (elem == NULL){ - malloc_heap_add_memzone(heap, size, align); - elem = find_suitable_element(heap, size, align, &prev); + if ((malloc_heap_add_memzone(heap, size, align)) == 0) + elem = find_suitable_element(heap, size, align, &prev); } - if (elem != NULL) + + if (elem != NULL){ elem = malloc_elem_alloc(elem, size, align, prev); + /* increase heap's count of allocated elements */ + heap->alloc_count++; + } rte_spinlock_unlock(&heap->lock); return elem == NULL ? NULL : (void *)(&elem[1]); + +} + +/* + * Function to retrieve data for heap on given socket + */ +int +malloc_heap_get_stats(struct malloc_heap *heap, + struct rte_malloc_socket_stats *socket_stats) +{ + if (!heap->initialised) + return -1; + + struct malloc_elem *elem = heap->free_head; + + /* Initialise variables for heap */ + socket_stats->free_count = 0; + socket_stats->heap_freesz_bytes = 0; + socket_stats->greatest_free_size = 0; + + /* Iterate through free list */ + while(elem) { + socket_stats->free_count++; + socket_stats->heap_freesz_bytes += elem->size; + if (elem->size > socket_stats->greatest_free_size) + socket_stats->greatest_free_size = elem->size; + + elem = elem->next_free; + } + /* Get stats on overall heap and allocated memory on this heap */ + socket_stats->heap_totalsz_bytes = heap->total_size; + socket_stats->heap_allocsz_bytes = (socket_stats->heap_totalsz_bytes - + socket_stats->heap_freesz_bytes); + socket_stats->alloc_count = heap->alloc_count; + return 0; } + diff --git a/lib/librte_malloc/malloc_heap.h b/lib/librte_malloc/malloc_heap.h index b3250ba021..d52a34f826 100644 --- a/lib/librte_malloc/malloc_heap.h +++ b/lib/librte_malloc/malloc_heap.h @@ -52,6 +52,10 @@ void * malloc_heap_alloc(struct malloc_heap *heap, const char *type, size_t size, unsigned align); +int +malloc_heap_get_stats(struct malloc_heap *heap, + struct rte_malloc_socket_stats *socket_stats); + int rte_eal_heap_memzone_init(void); diff --git a/lib/librte_malloc/rte_malloc.c b/lib/librte_malloc/rte_malloc.c index a1664fecfc..0c76017222 100644 --- a/lib/librte_malloc/rte_malloc.c +++ b/lib/librte_malloc/rte_malloc.c @@ -178,12 +178,44 @@ rte_malloc_validate(void *ptr, size_t *size) *size = elem->size - elem->pad - MALLOC_ELEM_OVERHEAD; return 0; } + +/* + * Function to retrieve data for heap on given socket + */ +int +rte_malloc_get_socket_stats(int socket, + struct rte_malloc_socket_stats *socket_stats) +{ + struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; + + if (socket >= RTE_MAX_NUMA_NODES || socket < 0) + return -1; + + return malloc_heap_get_stats(&mcfg->malloc_heaps[socket], socket_stats); +} + /* - * TODO: Print stats on memory type. If type is NULL, info on all types is printed + * Print stats on memory type. If type is NULL, info on all types is printed */ void rte_malloc_dump_stats(__rte_unused const char *type) { + unsigned int socket; + struct rte_malloc_socket_stats sock_stats; + /* Iterate through all initialised heaps */ + for (socket=0; socket< RTE_MAX_NUMA_NODES; socket++) { + if ((rte_malloc_get_socket_stats(socket, &sock_stats) < 0)) + continue; + + printf("Socket:%u\n", socket); + printf("\tHeap_size:%zu,\n", sock_stats.heap_totalsz_bytes); + printf("\tFree_size:%zu,\n", sock_stats.heap_freesz_bytes); + printf("\tAlloc_size:%zu,\n", sock_stats.heap_allocsz_bytes); + printf("\tGreatest_free_size:%zu,\n", + sock_stats.greatest_free_size); + printf("\tAlloc_count:%u,\n",sock_stats.alloc_count); + printf("\tFree_count:%u,\n", sock_stats.free_count); + } return; } @@ -196,4 +228,3 @@ rte_malloc_set_limit(__rte_unused const char *type, { return 0; } - diff --git a/lib/librte_malloc/rte_malloc.h b/lib/librte_malloc/rte_malloc.h index 687ab16420..b094b66da3 100644 --- a/lib/librte_malloc/rte_malloc.h +++ b/lib/librte_malloc/rte_malloc.h @@ -47,6 +47,18 @@ extern "C" { #endif +/** + * Structure to hold heap statistics obtained from rte_malloc_get_socket_stats function. + */ +struct rte_malloc_socket_stats { + size_t heap_totalsz_bytes; /**< Total bytes on heap */ + size_t heap_freesz_bytes; /**< Total free bytes on heap */ + size_t greatest_free_size; /**< Size in bytes of largest free block */ + unsigned free_count; /**< Number of free elements on heap */ + unsigned alloc_count; /**< Number of allocated elements on heap */ + size_t heap_allocsz_bytes; /**< Total allocated bytes on heap */ +}; + /** * This function allocates memory from the huge-page area of memory. The memory * is not cleared. In NUMA systems, the memory allocated resides on the same @@ -263,6 +275,21 @@ rte_free(void *ptr); int rte_malloc_validate(void *ptr, size_t *size); +/** + * Get heap statistics for the specified heap. + * + * @param socket + * An unsigned integer specifying the socket to get heap statistics for + * @param socket_stats + * A structure which provides memory to store statistics + * @return + * Null on error + * Pointer to structure storing statistics on success + */ +int +rte_malloc_get_socket_stats(int socket, + struct rte_malloc_socket_stats *socket_stats); + /** * Dump statistics. * -- 2.20.1