使用 mmap 和大页面随机读取大文件

Randomly read large file with mmap and huge pages

我正在使用 mmap 读取一个大型数据库文件(比如 100GB),其索引保存在主内存中(键偏移对)。

由于默认的 4KB 虚拟内存页面大小,我假设文件系统上的读取调用也将使用 4KB 的块。但是,这对于我的应用程序的访问模式来说效率很低。因此,我正在研究使用大页面透明地将 I/O 单元的大小从 4KB 增加到 2MB 的可能性。

大页面的典型用途似乎是改善内存分配和 TLB 利用率,但我找不到任何关于它与实际文件有何关系的信息 I/O。使用 mmap,似乎只有私有匿名映射才支持大页面。这个假设正确吗?我也尝试查看 libhugetlbfs,但找不到如何用它读取实际文件。

那么,有没有一种方法可以使用 mmap 透明地访问文件并使用 I/O 个大于 4KB 的单元?

Linux 不支持使用带页面缓存的大页面(与其他操作系统相同)。

最重要的原因是页面缓存被系统中的每个进程和内核本身使用(共享)。

考虑以下场景:您的进程映射文件使用 2MB 大页面,但另一个进程使用常规 4KB 页面映射它。做到这一点的唯一方法是将您的进程动态切换到 4KB 页面,因此首先从 2MB 页面开始是没有意义的。

您真正需要的是要求内核使用 fadvise with FADV_WILLNEED or madviseMADV_WILLNEED 开始预取数据。进行系统调用不是 "free",但如果您知道您很快将要访问 2MB 区域,那么它们应该是完美的。

有关更多信息,您可以阅读 this 以更深入地了解内核开发人员对大页面的看法。