前言:本文是对DPDK 20.11.0版本开发者文档 9.Mempool Library章节的翻译。
翻译目的:个人爱好;工作所需;予人参考。
翻译时间:2020/12/27
原文:https://doc.dpdk.org/guides/prog_guide/mempool_lib.html
DPDK版本:20.11.0
正文:
内存池是固定大小对象的分配器。在DPDK中,它通过名称进行标识,并使用mempool handler来存储空闲对象。默认的mempool handler是基于环的。它提供了一些其他可选服务,例如per-core缓存和对齐帮助,以确保填充对象以将其平均分布在所有DRAM或DDR3通道上。
该库由Mbuf库使用。
9.1 Cookies
在调试模式下,cookies被添加到分配的块的开头和结尾。然后,分配的对象包含覆盖保护字段,以帮助调试缓冲区溢出。
9.2 Stats
在调试模式下,有关从池中获取/放入池的统计信息存储在内存池结构中。统计信息是per-lcore的,以避免同时访问统计计数器。
9.3 x86体系结构上的内存对齐约束
根据X86架构上的硬件内存配置,可以通过在对象之间添加特定的填充来极大地提高性能。目的是确保每个对象在不同的通道上开始并在内存中排序,以便所有通道负载均衡。
对于执行L3转发或流分类的数据包缓冲区,尤其如此。仅前64个字节可访问,因此可以通过在不同通道之间分布对象的起始地址来提高性能。
任何DIMM上的rank是DIMM的完整数据位宽可访问的独立DRAM集的数量。等级无法共享,因为它们共享相同的数据路径。DIMM上的DRAM芯片的物理布局不一定与等级数有关。
在运行应用程序时,EAL命令行选项提供了添加内存channel和rank数量的能力。
Note:
命令行必须始终为处理器指定内存通道数。
图9.1和图9.2显示了不同DIMM体系结构的对齐示例。
在这种情况下,假设一个数据包是16个64字节的块,这是不正确的。
英特尔®5520芯片组具有三个通道,因此在大多数情况下,对象之间无需填充(大小为n x 3 x 64字节块的对象除外)。
创建新池时,用户可以指定是否使用此功能。
9.4 Local Cache
就CPU使用而言,多个核访问内存池的空闲缓冲区环的的成本可能很高,因为每个访问都需要compare-and-set(CAS)操作。为避免对内存池的环有太多的的访问请求,内存池分配器可以维护per-core cache,并通过缓存对内存池的环进行批量请求,通过缓存这种方法对实际内存池结构的锁定要少得多。这样,每个内核都可以完全访问自己的空闲对象缓存(带有锁),并且只有当缓存填满时,内核才需要将一些空闲对象转移回池环,或者在缓存为空时获取更多对象。
尽管这可能意味着许多buffer可能闲置在某些core的缓存上,但是内核无需加锁即可通过自身缓存来访问特定内存池。这提高了性能。
缓存由一个小的 per-core指针表及其长度(用作堆栈)组成。此内部缓存可以在创建池时启用或禁用。
cache的最大大小是静态的,并且在编译时定义(RTE_MEMPOOL_CACHE_MAX_SIZE)。
图9.3显示了一个缓存操作。
除了内部默认的per-lcore本地缓存之外,应用程序还可以通过调用rte_mempool_cache_create(),rte_mempool_cache_free()和rte_mempool_cache_flush()来创建和管理外部缓存。这些用户拥有的缓存可以显式传递到rte_mempool_generic_put()和rte_mempool_generic_get()。rte_mempool_default_cache()可被调用返回默认的内部缓存(如果有)。与默认缓存相反,未注册的非EAL线程也可以使用用户拥有的缓存。
9.5 Mempool Handlers
这允许外部存储器子系统(例如外部硬件存储器管理系统和基于软件的存储器分配器)与DPDK一起使用。
mempool handler有两个方面:
(1)为新的内存池操作(ops)添加代码。这可以通过添加新的内存池操作代码并使用MEMPOOL_REGISTER_OPS宏来实现。 (2)使用新的API调用rte_mempool_create_empty()和rte_mempool_set_ops_byname()来创建新的内存池并指定要使用的操作。
几个不同的mempool handler可以在同一应用程序中使用。可以使用rte_mempool_create_empty()函数创建一个新的内存池,然后使用rte_mempool_set_ops_byname()将mempool指向相关的mempool处理程序回调(ops)结构。
旧版应用程序可能会继续使用旧的rte_mempool_create()API调用,该调用默认情况下使用基于环的内存池处理程序。这些应用程序将需要修改以使用新的内存池处理程序。
对于使用rte_pktmbuf_create()的应用程序,有一个配置设置(RTE_MBUF_DEFAULT_MEMPOOL_OPS),允许应用程序使用替代的内存池处理程序。
Note:
当运行带有共享库的DPDK应用程序时,将动态加载使用“ -d” EAL命令行参数指定的内存池处理程序共享对象。当运行带有共享库的多进程应用程序时,必须以相同顺序为所有进程指定mempool处理程序的-d参数,以确保正确操作。
9.6 Use Cases
所有需要高性能的分配都应使用基于池的内存分配器。以下是一些示例:
Mbuf 库
EAL,用于日志服务
需要在数据平面中分配固定大小的对象并且系统将连续使用的任何应用程序。