43

可能重复:
mmap() 与读取块

我听说(在互联网上某处阅读)mmap()比顺序 IO 更快。它是否正确?如果是,那么为什么它更快?

  • mmap()不是按顺序阅读。
  • mmap()必须像从磁盘本身获取read()一样
  • 映射区域不是连续的 - 所以没有 DMA (?)。

那么mmap()实际上应该比read()文件慢吗?我上面的哪个假设是错误的?

4

3 回答 3

68

我听说(在互联网上某处阅读) mmap() 比顺序 IO 更快。它是否正确?如果是,那么为什么它更快?

可以 - 有利有弊,如下所列。 当您真的有理由关心时,请始终对两者进行基准测试

除了实际的 IO 效率之外,应用程序代码在需要执行 I/O 时跟踪的方式以及进行数据处理/生成的方式也会产生影响,这有时会极大地影响性能。

1) mmap() 没有按顺序读取。2) mmap() 必须从磁盘本身获取,与 read() 一样 3) 映射区域不是连续的 - 所以没有 DMA(?)。

所以 mmap() 实际上应该比文件中的 read() 慢?我上面的哪个假设是错误的?

1) 错误...mmap()分配与文件内容相对应的虚拟地址空间区域...每当访问该地址空间中的页面时,会发现物理 RAM 支持虚拟地址,并且相应的磁盘内容错误地进入该 RAM . 因此,从磁盘读取的顺序与访问顺序相匹配。这是一种“惰性”I/O 机制。例如,如果您需要索引一个要从磁盘读取的巨大哈希表,那么mmap读取文件并开始访问意味着磁盘 I/O 不是按顺序完成的,因此可能会导致整个文件被读入内存之前经过的时间更长,但是当这种情况发生时,查找会成功并且可以进行相关的工作,并且如果文件的某些部分从未真正需要,则不会读取它们(考虑到磁盘和内存页面的粒度,即使使用内存映射,许多操作系统也允许您指定一些关于您计划的性能增强/内存效率提示访问模式,以便他们可以主动提前读取或更积极地释放内存,因为他们知道您不太可能返回它)。

2) 绝对正确

3)“映射区域不连续”含糊不清。内存映射区域在虚拟地址空间中是“连续的”(连续的)。我们已经在上面讨论了磁盘 I/O 是顺序的。或者,你在想别的吗?无论如何,当页面出现故障时,它们确实可能使用 DMA 传输。

此外,内存映射可能优于通常的 I/O 还有其他原因:

  • 复制更少:
    • 通常操作系统和库级例程在数据到达应用程序指定的缓冲区之前通过一个或多个缓冲区,然后应用程序动态分配存储空间,然后从 I/O 缓冲区复制到该存储空间,以便在文件读取完成后数据可用
    • 内存映射允许(但不强制)就地使用(您可以只记录一个指针和可能的长度)
      • 继续就地访问数据的风险会增加以后的交换:文件/内存映射可能比可以解析的数据结构更冗长,因此其中数据的访问模式可能会在更多内存页面中出现更多延迟故障
  • 内存映射可以通过让应用程序将整个文件内容视为可访问来简化应用程序的解析工作,而不用担心何时读取另一个缓冲区已满
  • 应用程序更多地遵从操作系统对物理 RAM 中任何单个时间点的页数的明智判断,从而有效地与应用程序共享直接访问磁盘缓存
  • 正如下面的祝福评论,“使用内存映射,您通常会使用更少的系统调用”
  • 如果多个进程正在访问同一个文件,它们应该能够共享物理支持页面

这也是mmap可能变慢的原因 - 请阅读 Linus Torvald 的帖子,其中提到mmap

...页表游戏以及错误(甚至只是 TLB 未命中)开销很容易超过以流式传输方式复制页面的成本...

他的另一个帖子中:

  • 相当明显的安装和拆卸成本。我的意思是引人注目。就像按照页表干净地取消映射所有内容一样。这是维护所有映射列表的簿记。这是取消映射后需要的 TLB 刷新。

  • 页面错误是昂贵的。这就是映射被填充的方式,而且速度很慢。

FWIW,这是我最后一次在工作中出现的情况,在 64 位 Linux 上,内存映射输入比fread等人将二进制数据库记录读入专有数据库快 80%,文件约为 170GB。

于 2012-03-22T08:07:58.343 回答
13
  1. mmap()可以在进程之间共享。
  2. 将尽可能使用 DMA。DMA 不需要连续内存——许多高端卡都支持分散-聚集 DMA。
  3. 如果可能,内存区域可以与内核块缓存共享。所以有出租人抄袭。
  4. 内存mmap是由内核分配的,它总是对齐的。
于 2012-03-22T07:49:35.550 回答
6

绝对意义上的“更快”是不存在的。您必须指定限制条件和情况。

mmap() 没有按顺序读取。

什么让你有那个想法?如果您真的按顺序访问映射内存,系统通常会按该顺序获取页面。

mmap() 必须像 read() 一样从磁盘本身获取

当然,但操作系统确定时间和缓冲区大小

映射区域不是连续的 - 所以没有 DMA (?)。

往上看

有帮助的是mmap不涉及额外的用户空间缓冲区,“读取”发生在操作系统内核认为合适的地方,并且可以优化的块。这可能是速度上的优势,但首先这只是一个更易于使用的界面。

如果您想了解特定设置(硬件、操作系统、使用模式)的速度,则必须进行测量。

于 2012-03-22T07:12:01.727 回答