最近在看dpdk(dpdk.org)中关于hugepage的代码。我看到代码故意使虚拟地址在物理地址区域中连续。具体来说,它首先检查hugepages中是否存在物理上连续的zone,并将物理上连续的zone映射到连续的虚拟地址上。这如何提高性能?
To reserve a big contiguous amount of memory, we use the hugepage feature of linux. For that, we need to have hugetlbfs mounted. This code will create many files in this directory (one per page) and map them in virtual memory. For each page, we will retrieve its physical address and remap it in order to have a virtual contiguous zone as well as a physical contiguous zone.
为什么需要重新映射?
最佳答案
map the physically contiguous zone into contiguous virtual address. How does this improve the performance?
DPDK需要物理地址和虚拟地址。虚拟地址通常用于加载/存储一些数据。物理地址对于用户空间驱动程序向设备传输数据/从设备传输数据是必需的。
比如我们分配了几个mbuf
s 与虚拟地址 0x41000
, 0x42000
和 0x43000
.然后我们用一些数据填充它们并将这些虚拟地址传递给 PMD 进行传输。
驱动程序必须将这些虚拟地址转换为物理地址。如果物理页面不连续地映射到虚拟地址空间,要将虚拟地址转换为物理地址,我们需要搜索所有映射。例如虚拟地址0x41000
可能对应物理 0x81000
, 0x42000
对应0x16000
, 和 0x43000
— 至 0x64000
.
这种搜索的最佳情况是一次内存读取,最坏的情况是 - 每个缓冲区读取几次内存。
但是如果我们确定内存区域的虚拟地址和物理地址是连续的,我们只需将偏移量添加到虚拟地址即可获得物理地址,反之亦然。例如,虚拟 0x41000
对应0x81000
, 虚拟 0x42000
到物理0x82000
, 和 0x43000
— 0x83000
.
我们从映射中知道的偏移量。这种翻译的最坏情况是突发中对所有缓冲区读取一次内存,这对翻译来说是一个巨大的改进。
Why is this remapping necessary?
将大页面映射到虚拟地址空间 mmap
使用系统调用。调用的 API 允许为要映射的大页面指定固定的虚拟地址。这允许一个接一个地映射大页面,创建一个连续的虚拟内存区域。例如,我们可以mmap
虚拟地址的大页面 0x200000
,虚拟地址下一个0x400000
等等。
不幸的是,在映射之前我们不知道大页面的物理地址。所以在虚拟地址 0x200000
我们可能会映射物理地址 0x800000
, 以及虚拟地址 0x400000
— 物理 0x600000
.
但是一旦我们第一次映射了那些大页面,我们就知道了物理地址和虚拟地址。所以我们需要做的是以正确的顺序重新映射它们:在虚拟地址0x1200000
我们图实物0x600000
,并在 0x1400000
— 物理 0x800000
.
现在我们有一个虚拟和物理上连续的内存区域,从虚拟地址0x1200000
开始。和物理地址0x600000
.因此,要将此内存区域中的虚拟地址转换为物理地址,我们只需要减去偏移量 0x600000
。来自如前所述的虚拟地址。
希望这能稍微阐明连续内存区域和重新映射的概念。
关于c - 使物理地址区域中的虚拟地址连续如何提高性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55804818/