memory: stats for malloc
authorIntel <intel.com>
Wed, 19 Dec 2012 23:00:00 +0000 (00:00 +0100)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Thu, 25 Jul 2013 13:23:27 +0000 (15:23 +0200)
Signed-off-by: Intel
lib/librte_eal/common/include/rte_malloc_heap.h
lib/librte_malloc/malloc_elem.c
lib/librte_malloc/malloc_elem.h
lib/librte_malloc/malloc_heap.c
lib/librte_malloc/malloc_heap.h
lib/librte_malloc/rte_malloc.c
lib/librte_malloc/rte_malloc.h

index d5ea63e..758b4fc 100644 (file)
@@ -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_ */
index 0d2fdb6..0127917 100644 (file)
@@ -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;
 }
 
index 5c7a428..5cd6445 100644 (file)
@@ -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 */
index 0b35074..bba34dc 100644 (file)
@@ -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;
 }
+
index b3250ba..d52a34f 100644 (file)
@@ -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);
 
index a1664fe..0c76017 100644 (file)
@@ -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;
 }
-
index 687ab16..b094b66 100644 (file)
 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.
  *