mmap是否直接访问页面缓存或页面缓存的副本?

时间:2017-09-13 06:54:38

标签: caching linux-kernel mmap page-caching

要以另一种方式提问,你能否确认当mmap()你实际访问已经在页面缓存中的确切物理页面的文件时?

我问,因为我正在测试一台带有1TB RAM的192核心机器,测试前预先缓存到页面缓存中的400GB数据文件(只需删除缓存,然后执行md5sum)文件)。

最初,我让所有192个线程分别对文件进行mmap,假设它们都会(基本上)获得(基本上)相同的内存区域(或者可能是相同的内存区域但以某种方式多次映射)。因此,我假设使用两个不同映射到同一文件的两个线程都可以直接访问相同的页面。 (在这个例子中我们忽略NUMA,但显然它在较高的线程数时很重要。)

然而,实际上我发现当每个线程分别对文件进行映射时,性能会在更高的线程数下变得可怕。当我们删除它而只是做了一个传递给线程的mmap(这样所有线程只是直接访问相同的内存区域),然后性能显着提高了

这一切都很棒,但我想弄明白为什么。如果事实上mmapping文件只是授予对现有页面缓存的直接访问权限,那么我认为映射它的次数应该无关紧要 - 它应该全部转到完全相同的位置。

但鉴于存在这样的性能成本,在我看来,实际上每个mmap都是独立且冗余填充的(可能是通过从页面缓存中复制,或者可能是从磁盘再次读取)。

您能否评论为什么我在同一内存的共享访问与映射同一文件之间看到如此不同的性能?

谢谢,感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

我想我找到了答案,它处理了页面目录。答案是肯定的,同一文件的两个mmapped区域将访问相同的底层页面缓存数据。但是,每个映射都需要将每个虚拟页面独立映射到物理页面 - 这意味着页面目录中的条目数量是访问同一RAM的2倍。

基本上,每个mmap()都在虚拟内存中创建一个新范围。该范围的每个页面对应一个物理内存页面,该映射存储在分层页面目录中 - 每4KB页面有一个条目。因此,大区域的每个mmap()都会在页面目录中生成大量条目。

我的猜测是它实际上并没有预先定义它们,这就是为什么即使对于一个巨大的文件,mmap()也可以即时调用。但随着时间的推移,它可能必须建立这些条目,因为mmapped范围存在缺陷,这意味着随着时间的推移它被填写。填充页面目录的额外工作可能是使用不同mmaps的线程比共享同一mmap的线程慢的原因。我打赌内核需要在取消映射范围时擦除所有这些条目 - 这就是unmmap()速度太慢的原因。

(还有翻译后备缓冲区,但这是每个CPU,而且这么小我认为这不重要。)

无论如何,这听起来像重新映射相同的区域只会增加额外的开销,因为在我看来似乎没有收获。