如何在程序运行时获取 dpdk-16.04 大页使用情况?

前言

基于 dpdk-16.04 开发的 dpdk 程序需要使用的大页内存总大小可以通过计算得出,但由于 dpdk-16.04 legacy memory 模型只支持物理地址连续的 segment 内存分配方式,在系统启动后再动态设置大页时,物理地址相对离散,则没有较大的 memseg 来分配。

这样如果要分配一块非常大的空间,尽管小于总的大页内存空间,仍有可能因为最大的 memseg 大小不足而分配失败。

为了解决这个问题,大页的预留方式可以修改为通过内核启动参数配置预留。这种方式只能让大页内存的物理地址相较系统启动后分配相对集中,但常常还是需要分配更多的大页来增大单个 segment 能够分配的最大空间。

而当大页内存预留后其它程序能够使用的内存空间减少,大页的数量分配不合理就会造成内存浪费。如果有一种方式能够在运行时观测 dpdk 内部大页的使用情况,并找到最大的 memseg 空间,也许就可以适当减少大页的数量,为其它进程留出更多的内存、使用更少的内存条。

如何在 dpdk 程序运行时获取大页使用情况?

在 lib/librte_eal/common/malloc_heap.c 文件中有如下函数:

int
malloc_heap_get_stats(const struct malloc_heap *heap,
		struct rte_malloc_socket_stats *socket_stats)
{
	size_t idx;
	struct malloc_elem *elem;

	/* 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 */
	for (idx = 0; idx < RTE_HEAP_NUM_FREELISTS; idx++) {
		for (elem = LIST_FIRST(&heap->free_head[idx]);
			!!elem; elem = LIST_NEXT(elem, free_list))
		{
			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;
		}
	}
	/* 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;
}

此函数遍历指定的 malloc_heap 上的 free_list 来 dump 空闲空间及最大可分配的空间,可以在外部程序中调用此函数来 dump 信息。dpdk 中每一个 numa 节点的大页内存都会分配一个 malloc_heap 结构,此结构保存在 rte_config 共享内存中,可以获取到 rte_config 的内容,遍历每一个 malloc_heap 结构,调用 malloc_heap_get_stats 来获取大页的使用数据。

测试方法

修改 l2fwd 程序源码,在 dpdk rte_eal_init 初始化后执行 pause 暂停。同时修改 proc_info 代码,在调用 mem_display 前按照上文描述的方法调用 malloc_heap_get_stats 函数 dump 信息。

先运行 l2fwd 程序,然后运行 proc_info 程序观测大页内存内部使用情况。

测试记录

在系统开机后设置 49 个 2M 大页(都在 numa 0 上),当 l2fwd 运行后,添加 -m 参数运行 proc_info 程序,终端输出信息部分摘录如下:

numa 0 biggest_free_size is 6291392
numa 0 total_len is 102757824 byte, free_size is 100086528 byte
numa 0 total_len is 97m, free_size is 95m
----------- MEMORY_SEGMENTS -----------
Segment 0: phys:0x71c00000, len:2097152, virt:0x7fec3e000000, socket_id:0, hugepage_sz:2097152, nchannel:0, nrank:0
Segment 1: phys:0x74400000, len:4194304, virt:0x7fec3da00000, socket_id:0, hugepage_sz:2097152, nchannel:0, nrank:0
Segment 2: phys:0x75000000, len:2097152, virt:0x7fec3d600000, socket_id:0, hugepage_sz:2097152, nchannel:0, nrank:0
Segment 3: phys:0x75800000, len:2097152, virt:0x7fec3d200000, socket_id:0, hugepage_sz:2097152, nchannel:0, nrank:0
Segment 4: phys:0x75c00000, len:4194304, virt:0x7fec3cc00000, socket_id:0, hugepage_sz:2097152, nchannel:0, nrank:0
Segment 5: phys:0x76400000, len:2097152, virt:0x7fec3c800000, socket_id:0, hugepage_sz:2097152, nchannel:0, nrank:0
Segment 6: phys:0x76e00000, len:2097152, virt:0x7fec3c400000, socket_id:0, hugepage_sz:2097152, nchannel:0, nrank:0
Segment 7: phys:0x77400000, len:2097152, virt:0x7fec3c000000, socket_id:0, hugepage_sz:2097152, nchannel:0, nrank:0
Segment 8: phys:0x77e00000, len:2097152, virt:0x7fec3bc00000, socket_id:0, hugepage_sz:2097152, nchannel:0, nrank:0
Segment 9: phys:0x78c00000, len:4194304, virt:0x7fec3b600000, socket_id:0, hugepage_sz:2097152, nchannel:0, nrank:0
Segment 10: phys:0x79400000, len:4194304, virt:0x7fec3b000000, socket_id:0, hugepage_sz:2097152, nchannel:0, nrank:0
Segment 11: phys:0x79a00000, len:6291456, virt:0x7fec3a800000, socket_id:0, hugepage_sz:2097152, nchannel:0, nrank:0
....................................................................................................................

最大的 free 空间为 6291392(内部数据占了一部分空间,故而小于 6291456),尽管总共有 98M 大页内存能够使用,但由于单次分配的内存必须物理空间连续(位于一个 segment),则最大分配 6291392(5.9M) 空间,说明此时物理内存已经非常离散。

总结

dpdk legacy 内存模型实现有些简陋,按照一般的思路,总的内存足够应该就能够分配出需要的空间,然而在 dpdk legacy 内存模型下却会受限于单块连续物理内存的最大值,使用内核启动参数预留内存算是一种规避方法,最好还是更新 dpdk 版本,新的内存模型已经解决了这一问题。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值