当前位置: 首页 > 面试题库 >

为什么mmap()比顺序IO快?

劳仲渊
2023-03-14
问题内容

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

  • mmap() 没有按顺序阅读。
  • mmap()已经从磁盘读取本身一样read()
  • 映射区域不是顺序的-因此没有DMA(?)。

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


问题答案:

我听说(在互联网上的某处阅读)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,这是我上一次出现这种情况时fread,在具有170GB文件的64位Linux上,内存映射输入比将二进制数据库记录读取到专有数据库中的速度快80%。



 类似资料:
  • 我发现 比 Python 2 和 3 中的函数慢。 Python 2 蟒蛇 3 为什么<code>max</code>(<code>O(n)</code>)比<code>sort</code>函数(<code<O(nlogn)</code>)慢?

  • 问题内容: 原始问题: 当我的JavaScript调用的功能在页面下方而不是在调用页面的下方定义时,JSHint会抱怨。但是,我的页面是用于游戏的,在下载全部内容之前,不会调用任何函数。那么为什么订单功能出现在我的代码中很重要? 我在里面吟。看来我需要花另一天的时间才能重新排序六千行代码。使用javascript的学习曲线一点也不陡峭,但是非常糟糕。 问题答案: tl; dr 如果在加载完成之前不

  • 问题内容: 在检查null时,我使用以下方法: 但我也看到了这一点: 使用一个相对于另一个有什么优势吗?还是只是为了提高可读性? 问题答案: 第二个版本()称为 yoda条件 。 它们都导致相同的行为,但是第二个优点是:当您忘记一个变量时,它可以防止您意外地更改变量。在这种情况下,编译器将在该行返回错误,并且您不会再遇到一些奇怪的代码行为和调试结果。

  • 问题内容: 示例代码在这里 问题答案: 我认为速度更快,因为使用矢量化方式和熊猫构建在此数组上。 慢,因为它使用。 操作是最快的,然后是。 请参阅此答案,并更好地解释pandas开发人员。

  • 问题内容: 我不知道为什么numba在这里击败numpy(超过3倍)。我在这里进行基准测试时是否犯了一些根本性的错误?对于numpy来说似乎是完美的情况,不是吗?请注意,作为检查,我还运行了一个结合了numba和numpy的变体(未显示),正如预期的那样,它与不带numba的numpy运行相同。 (顺便说一下,这是一个后续问题:数字处理二维数组的最快方法:dataframe vs series v

  • 问题内容: [编辑:此问题仅适用于32位系统。 如果您的计算机,操作系统和python实现是64位的,则映射大型文件将可靠且非常有效。] 我正在编写一个模块,该模块除其他功能外,还允许对文件进行按位读取访问。这些文件可能很大(数百GB),因此我编写了一个简单的类,使我可以像对待字符串一样对待文件,并隐藏所有查找和读取内容。 当时我写了包装类,我对mmap模块一无所知。在阅读mmap的文档时,我认为