【问题标题】:Randomly read large file with mmap and huge pages使用 mmap 和大页面随机读取大文件
【发布时间】:2023-03-21 10:46:01
【问题描述】:

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

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

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

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

【问题讨论】:

  • 您需要 很多 的 RAM 才能做到这一点。每次您需要读取尚未在内存中的数据时,如果没有任何 2 MB 可用页面,内核将不得不合并一个。太多(并且不会花费太多......)将导致灾难性的性能问题,并可能唤醒 OOM 杀手。每次随机读取会访问多少数据?如果它不在 MB 范围内或更大,如果需要逐出映射页面以引入所需的数据,即使您只读取 1 个字节,也需要读取 2MB。对这个 mmap 解决方案和其他解决方案进行基准测试,例如使用 pread()
  • 感谢您的评论,但它并没有解决如何实际读取大页面文件的问题。在研究性能问题之前,我想知道这是否可能。谢谢。

标签: linux io mmap memory-mapped-files huge-pages


【解决方案1】:

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

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

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

您真正需要的是让内核使用fadviseFADV_WILLNEEDmadviseMADV_WILLNEED 开始预取数据。进行系统调用不是“免费”的,但如果您知道您将很快访问 2MB 区域,那么它们应该是完美的。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-08
    • 2015-11-26
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    • 2012-06-04
    • 1970-01-01
    相关资源
    最近更新 更多