Mempool 庫
內存池是固定大小的對象分配器。 在DPDK中,它由名稱唯一標識,並且使用mempool操作來存儲空閑對象。 默認的mempool操作是基於ring的。它提供了一些可選的服務,如per-core緩存和對齊幫助,以確保對象被填充, 方便將他們均勻擴展到DRAM或DDR3通道上。
這個庫由 Mbuf Library 使用。
1.2. Stats
在調試模式(CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG is enabled)中,從池中獲取/釋放的統計信息存放在mempool結構體中。 統計信息是per-lcore的,避免並發訪問統計計數器。
1.3. 內存對齊約束
根據硬件內存配置,可以通過在對象之間添加特定的填充來大大提高性能。 其目的是確保每個對象開始於不同的通道上,並在內存中排列,以便實現所有通道負載均衡。
特別是當進行L3轉發或流分類時,報文緩沖對齊尤為重要。此時僅訪問報文的前64B,因此可以通過在不同的信道之間擴展對象的起始地址來提升性能。
DIMM上的rank數目是可訪問DIMM完整數據位寬的獨立DIMM集合的數量。 由於他們共享相同的路徑,因此rank不能被同事訪問。 DIMM上的DRAM芯片的物理布局無需與rank數目相關。
當運行app時,EAL命令行選項提供了添加內存通道和rank數目的能力。
Note
命令行必須始終指定處理器的內存通道數目。
不同DIMM架構的對齊示例如圖所示 Fig. 5.1 及 Fig. 5.2 。

Fig. 5.1 Two Channels and Quad-ranked DIMM Example
在這種情況下,假設吧平穩是64B塊就不成立了。
Intel® 5520芯片組有三個通道,因此,在大多數情況下,對象之間不需要填充。(除了大小為n x 3 x 64B的塊)

Fig. 5.2 Three Channels and Two Dual-ranked DIMM Example
當創建一個新池時,用戶可以指定使用此功能。
1.4. 本地緩存
在CPU使用率方面,由於每個訪問需要compare-and-set (CAS)操作,所以多核訪問內存池的空閑緩沖區成本比較高。 為了避免對內存池ring的訪問請求太多,內存池分配器可以維護per-core cache,並通過實際內存池中具有較少鎖定的緩存對內存池ring執行批量請求。 通過這種方式,每個core都可以訪問自己空閑對象的緩存(帶鎖), 只有當緩存填充時,內核才需要將某些空閑對象重新放回到緩沖池ring,或者當緩存空時,從緩沖池中獲取更多對象。
雖然這意味着一些buffer可能在某些core的緩存上處於空閑狀態,但是core可以無鎖訪問其自己的緩存提供了性能上的提升。
緩存由一個小型的per-core表及其長度組成。可以在創建池時啟用/禁用此緩存。
緩存大小的最大值是靜態配置,並在編譯時定義的(CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE)。
Fig. 5.3 顯示了一個緩存操作。

Fig. 5.3 A mempool in Memory with its Associated Ring
不同於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線程使用。
1.5. Mempool 句柄
這允許外部存儲子系統,如外部硬件存儲管理系統和軟件存儲管理與DPDK一起使用。
mempool 操作包括兩方面:
- 添加新的mempool操作代碼。這是通過添加mempool ops代碼,並使用
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處理回調(ops)結構體。
傳統的應用程序可能會繼續使用舊的 rte_mempool_create()
API調用,它默認使用基於ring的mempool處理。 這些應用程序需要修改為新的mempool處理。
對於使用 rte_pktmbuf_create()
的應用程序,有一個配置設置(RTE_MBUF_DEFAULT_MEMPOOL_OPS
),允許應用程序使用另一個mempool處理。
1.6. Mempool
DPDK以兩種方式對外提供內存管理方法,一個是rte_mempool,主要用於網卡數據包的收發;一個是rte_malloc,主要為應用程序提供內 存使用接口。本文討論rte_mempool。rte_mempool由函數rte_mempool_create()負責創建,從 rte_config.mem_config->free_memseg[]中取出合適大小的內存,放到 rte_config.mem_config->memzone[]中。
rte_mempool結構體:
1 /** 2 * The RTE mempool structure. 3 */ 4 struct rte_mempool { 5 /* 6 * Note: this field kept the RTE_MEMZONE_NAMESIZE size due to ABI 7 * compatibility requirements, it could be changed to 8 * RTE_MEMPOOL_NAMESIZE next time the ABI changes 9 */ 10 char name[RTE_MEMZONE_NAMESIZE]; /**< Name of mempool. */ 11 RTE_STD_C11 12 union { 13 void *pool_data; /**< Ring or pool to store objects. */ 14 uint64_t pool_id; /**< External mempool identifier. */ 15 }; 16 void *pool_config; /**< optional args for ops alloc. */ 17 const struct rte_memzone *mz; /**< Memzone where pool is alloc'd. */ 18 unsigned int flags; /**< Flags of the mempool. */ 19 int socket_id; /**< Socket id passed at create. */ 20 uint32_t size; /**< Max size of the mempool. */ 21 uint32_t cache_size; 22 /**< Size of per-lcore default local cache. */ 23 24 uint32_t elt_size; /**< Size of an element. */ 25 uint32_t header_size; /**< Size of header (before elt). */ 26 uint32_t trailer_size; /**< Size of trailer (after elt). */ 27 28 unsigned private_data_size; /**< Size of private data. */ 29 /** 30 * Index into rte_mempool_ops_table array of mempool ops 31 * structs, which contain callback function pointers. 32 * We're using an index here rather than pointers to the callbacks 33 * to facilitate any secondary processes that may want to use 34 * this mempool. 35 */ 36 int32_t ops_index; 37 38 struct rte_mempool_cache *local_cache; /**< Per-lcore local cache */ 39 40 uint32_t populated_size; /**< Number of populated objects. */ 41 struct rte_mempool_objhdr_list elt_list; /**< List of objects in pool */ 42 uint32_t nb_mem_chunks; /**< Number of memory chunks */ 43 struct rte_mempool_memhdr_list mem_list; /**< List of memory chunks */ 44 45 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG 46 /** Per-lcore statistics. */ 47 struct rte_mempool_debug_stats stats[RTE_MAX_LCORE]; 48 #endif 49 } __rte_cache_aligned;