如何通过 DPDK API rte_malloc 跟踪内存分配?

How to track memory allocation via DPDK API rte_malloc?

基于 DPDK API 文档 rte_malloc_dump_stats 据说 将指定类型转储到文件 .但是自定义应用程序或 app/test/test_malloc.c 都没有共享所需的结果。

预期:对于 DPDK API rte_malloc、rte_calloc,rte_zmalloc 是用 const char *type 创建的。可以使用 rte_malloc_dump_stats

查询特定 const char *type 的统计数据

当前结果:DPDK API rte_malloc_dump_stats 给出了总体堆使用情况,没有任何关于哪种“类型”使用多少的信息。

问题:DPDK 中是否还有其他API 可用于跟踪大页面 malloc 使用情况?任何 DPDK 补丁都会有用吗?

示例代码流:

/* with huge page */
rte_eal_init 

/* create memory location for various object type */
rte_malloc ("objecttype-1")
rte_malloc ("objecttype-2")
rte_malloc ("objecttype-3")
rte_malloc ("objecttype-4")

/* dump stats for object type - 1 */
rte_malloc_dump_stats ("objecttype-1")

我的应用程序调用了 rte_calloc,它调用了一些其他的内部子例程,最后调用了 heap_alloc(其中“type”似乎是 unsed)。 heap_alloc(struct malloc_heap *heap, const char *type __rte_unused, size_t size, unsigned int flags, size_t align, size_t bound,布尔重叠群)。堆分配目前似乎忽略了“类型”参数。如何跟踪堆内存使用情况?

观察是正确的,目前DPDK API rte_malloc, rte_zalloc, rte_calloc丢弃了第一个参数表示的名称字段const char *type .因此使用 DPDK API rte_malloc_dump_stats 进行转储或查询不会 return 特定 const char *type.

这个问题有几个解决方法(无需修改 DPDK 库),例如

  1. rte_memzone_reserve创建一个命名区域(可以是想要的类型)作为替换。
  2. rte_mempool_create_empty 创建一个命名的空内存池。

两种方法都有其缺点

  1. memzone:通常针对较大的区域并调用一次,因此对小对象频繁调用 memzone_reserve 会影响性能。还必须使用 rte_memzone_walk 遍历所需的 const char *type 以获得详细信息。
  2. empty_mempool:期望放入的所有对象大小相同,因此它在创建可重用计数器池或列表等地方很有用。但是使用 rte_mempool_lookup 可以更轻松地访问池以获取元素数量、大小和每个内核缓存的元素等详细信息。

有一个简单得多的替代方法,只需创建 Create a container to hold malloc|calloc|zalloc name, pointer and size using fb_arry。在每次成功分配时,从 fb_array 中获取一个元素持有者并更新详细信息。这种方法的主要优点是 fb_arry can be extended on huge page via rte_memzone_reserve,这使得对 const char *type 的监控几乎无需修改。

代码片段:

struct rte_memzone *mptr = NULL;

struct elements {
    char name[256];
    void *ptr;
};

/* right after rte_eal_init */
mptr = rte_memzone_reserve_aligned("MALLOC_REGIONS",
            sizeof(struct rte_fbarray), SOCKET_ID_ANY,
            RTE_MEMZONE_2MB, 8);

/* create a wrapper or MACRO to insert details of each alloc with type field */
do
{
    ptr = rte_malloc(NULL, size_dataoibject, 0);
    if (ptr == NULL)
        return NULL;

    int index = rte_fbarray_find_next_free((struct rte_fbarray *)mptr->addr, 0);
    if (index < 0) {
        printf("fail in rte_fbarray_find_next_free %d", index);
        rte_free(ptr);
        return NULL;
    }

    return ptr;
} while(0);

/* in the data processing thread, invoke the MACRO/function*/

参考文献:

  1. DPDK debug guide
  2. malloc monitor