6. Mempool Library

来源:互联网 发布:java获取本地路径 编辑:程序博客网 时间:2024/06/10 23:34

        Memory pool是一个分配对象大小固定的内存分配器。 在DPDK中,它通过名称唯一标识,并使用mempool句柄存储空闲对象空间。 默认的mempool句柄是基于ring的。 mempool 提供了一些其他可选服务,例如核本地缓存和内存对齐辅助器,内存对齐辅助器确保对象被均匀地填充到所有DRAM或DDR3通道上(对象被均匀的放在通道上,会提高存取速度)。

        Mbuf 库基于memory库实现的。


6.1. Cookies(mempool添加的特定成员以保存内存分配信息)

        在调试模式时(使能CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG ), 分配块的前后将添加cookies。  于是分配对象中将包含覆盖保护字段,以帮助调试缓冲区溢出。


6.2. Stats

        在调试模式时(使能CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG ),分配统计信息保存在mempool结构中,每个核有自己的统计信息,以避免同步问题。


6.3. 内存对齐

        根据硬件的存储结构,在分配对象之间补零可以大大的提高性能。这样做的目的是确保每个分配对象的开始地址和内存中的channel和rank首地址对齐,以便均衡的加载到所有channel(对齐的目的是减少未命中的发生概率,channel和rank是内存的组成结构,详情需要了解内存的构造,不然这节有点难懂)。

        内存对齐的包缓存在三层转发和流分类时特别有用。仅仅访问头64自己的话,可以通过将对象的首地址均衡的分摊存储到不同的channels中来提高访存性能。

        DIMM中的ranks是一个个独立的装置存在于DRAMS中,ranks可以以DIMM的满带宽速度访问,但ranks不能同时被访问,因为它们共享相同的数据通路。DIMM中的DRAM芯片的物理布局本身并不一定与ranks的数量有关。

        在运行dpdk应用时,可以通过EAL命令行配置内存的channels和ranks。

note:命令配置的参数必须和指定的cpu的内存channels数匹配。

        图6.1和6.2展示了不同DIMM架构中对齐的例子


         在这个例子中,假定数据包的大小是64字节,占用16个块。

         Intel ®5520 芯片集有3个channels,在大多数情况,在分配对象之间不用填充(除了对象的大小是nx3x64字节的块)


        当创建一个新内存池时,用户可以指定是否使用这个特性。

注:上面提到的“内存对齐“不同于仅仅将数据放在一个合适的内存地址上,而是根据内存通道(channel)和rank的结构,将数据包拆分成块,均匀分布到不同的channel的rank上,,当存取一个数据报文时可以同时访问多个channel,获得性能提升。

6.4. 本地缓存

        多核cpu访问同一个内存池的ring中的空闲缓冲区时,代价会很大,因为每次存取都要进行compare-and-set (CAS)操作。为了避免对于一个内存池ring的太多存取请求,内存池分配器支持单核本地缓存,支持批量请求操作机制(在对ring的实际结构操作中较少使用有锁的缓存)。这样,每个核都可以满速访问自己的缓存中(带有锁)的空闲对象,只有当缓存填充时,核才需要将一些空闲对象拖回内存池中,或者在缓存为空时获得更多对象。

        虽然这可能意味着在某些核的缓存中许多分配对象可能会闲置,但是核通过访问没有锁的本地缓存来得到性能的提升。

        本地缓存由一个小的、核本地指针表和长度(用作堆栈)组成。这个内部缓存可以在创建内存池时启用或禁用。

        本地缓存的最大值在编译阶段就静态设置了(CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE)。

        

        另外内部的默认是核本地缓存,应用程序可以通过调用以下函数创建和管理外部缓存:

        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线程使用。


6.5. 内存池句柄

       mempool允许外部内存子系统,例如外部硬件内存管理系统和基于软件的内存分配程序,用于DPDK。

       mempool句柄包括两个方面:

       *为新的mempool操作(ops)添加代码。这是通过添加一个新的mempool操作码来实现的,并使用MEMPOOL_REGISTER_OPS宏来设置

       *使用新的API调用rte_mempool_create_empty()和rte_mempool_set_ops_byname()来创建一个新的mempool并指定要使用的操作。

       可以在同一个应用程序中使用几个不同的mempool 句柄。可以使用rte_mempool_create_empty()函数创建新的mempool,然后使用rte_mempool_set_ops_byname()将mempool指向相关的mempool句柄回调结构。

       旧的应用程序可能会继续使用旧的rte_mempool_create()API调用,默认情况下使用一个基于mempool 句柄的ring。需要对这些应用程序进行修改,以使用新的mempool处句柄。

       对于使用rte_pktmbuf_create()的应用程序,有一个配置设置(RTE_MBUF_DEFAULT_MEMPOOL_OPS),它允许应用程序使用另一个mempool句柄。


6.6. 用例

       所有需要高性能的内存分配都应该使用基于内存池的分配器。以下是一些例子:

       *Mbuf  Library

       *Environment Abstraction Layer(环境抽象层),日志服务

       *任何需要在数据平面中分配固定大小,不断使用的内存对象的应用程序

原创粉丝点击