本文介绍DPDK内存的基本原理,以及DPDK是如何利用这些特性来实现高性能的
现代CPU架构中,内存管理并不以单个字节进行,而是以页为单位,即虚拟和物理连续的内存块。通常系统默认页面大小为4KB。
如果其中一个页面不在TLB缓存中,尝试访问该页面中包含的地址将导致TLB查询失败;也就是说,操作系统写入TLB的页地址必须是在它的全局页表中进行查询操作获取的。因此,TLB查询失败的代价也相对较高,所以最好将当前活动的所有页面都置于TLB中以尽可能减少TLB查询失败。
在Linux里,大内存页默认是不开启的。DPDK依赖于标准大页。在英特尔x86_64架构上,目前可用的两种大页大小为2MB和1GB。单个页面可以覆盖2 MB或1 GB大小的整个物理和虚拟连续的存储区域
当分配常规内存时,理论上,它可以被分配到RAM中的任何位置。这在单CPU系统上没有什么问题,但是许多DPDK用户是在支持非统一内存访问 (NUMA) 的多CPU系统上运行应用的。对于NUMA来说,所有内存都是不同的,跨numa节点的内存访问比同节点的内存访问延迟要高得多。
DPDK 提供了在指定的NUMA节点分配内存的能力,避免出现大量的跨NUMA节点访问内存带来的延迟。
DPDK的内存管理中,每当一个内存区域可供DPDK使用时,DPDK就通过询问内核来计算它的物理地址。由于DPDK锁定内存,通常以大页的形式,底层内存区域的物理地址预计不会改变,因此硬件可以依赖这些物理地址始终有效,即使内存本身有一段时间没有使用。然后,DPDK会在准备由硬件完成的输入/输出事务时使用这些物理地址,并以允许硬件自己启动DMA事务的方式配置硬件。这使DPDK避免不必要的开销,并且完全从用户空间执行输入/输出。
DPDK使用自定义内存分配器,通过分配大页,并在此内存中创建一个堆同时将其提供给用户应用程序并用于存取应用程序内部的数据结构。
DPDK内存分配总是在CPU cache line的边界上对齐,每个分配的起始地址将是系统高速缓存行大小的倍数。
DPDK也有一个内存池管理器,在整个DPDK中广泛用于管理大型对象池,对象大小固定。
DPDK的共享内存通过映射不同进程中的相同资源来实现,同时还复制另一个进程的地址空间。因此,两个进程中的所有内容都位于相同的地址,指向DPDK内存对象的任何指针都将跨进程工作,无需任何地址转换。