在 Linux 上,假设我有一个可执行文件。让我们看两种情况:
(A)可执行文件所做的大部分工作是磁盘 I/O;
(二)可执行文件不执行任何磁盘 I/O。
对于每一种情况A和乙,我是否应该预期这两种情况之间可执行文件的运行时间会有显著差异?
(1)可执行文件和所有相关文件都位于 tmpfs 文件夹(RAM 文件夹)中;
(2)可执行文件和所有相关文件都位于“常规”磁盘文件夹中。
我还想知道与 Docker 相关的这三种场景之间是否存在显著差异:
(3)可执行文件在 Docker 容器内运行,并且可执行文件和所有相关文件都位于容器内创建的 tmpfs 文件夹中,该文件夹位于使用以下方式挂载的磁盘驱动器下docker run -v ...
(4)可执行文件在 Docker 容器内运行,并且可执行文件和所涉及的所有文件都位于容器内创建的 tmpfs 文件夹中,位于“内部”驱动器下(容器停止后不会保留)。
(5)可执行文件在 Docker 容器内运行,并且可执行文件和所涉及的所有文件都位于“常规”磁盘文件夹中。
我的预期是,一般来说,从 tmpfs 文件夹运行应该会更快,尤其是在涉及大量磁盘 I/O 的情况下。但在实践中我没有看到这一点,所以我想看看我的预期是否正确。
答案1
仅当您有大量无法从页面缓存中满足的磁盘 I/O 时,在 tmpfs 上运行才会更快。
如果读取 I/O 并且文件已经在缓存中,则 tmpfs 将不会产生任何影响。
如果 I/O 是异步写入而不刷新,并且工作负载是突发的而不是连续的,并且有足够的缓存来吸收突发的写入,并且可以在突发之间在后台刷新写入,则 tmpfs 将不会产生任何影响。
如果没有磁盘 I/O 需要执行,tmpfs 将不会产生任何影响。
如果您有大量磁盘 I/O,并且您的进程被阻塞,等待存储赶上进度,则在 tmpfs 上运行将产生巨大的差异。您的磁盘越慢,差异就越大,直到您成为 CPU 瓶颈。
答案2
(4) 可执行文件在 Docker 容器内运行,并且可执行文件和所涉及的所有文件都位于容器内创建的 tmpfs 文件夹中,位于“内部”驱动器下(容器停止后不会保留)。
(5)可执行文件在 Docker 容器内部运行,并且可执行文件和所涉及的所有文件都位于“常规”磁盘文件夹中。
除了 Tmpfs(已经解决)之外,您不会注意到在主机上运行可执行文件和在 Docker 容器内运行可执行文件之间的任何差异。卷存储也是如此。Docker 使用覆盖文件系统运行两者,并且可能存在非常覆盖的性能受到很小的影响,但主机会将可执行文件视为一个进程运行,就像在主机上启动一样。
答案3
实际上,差异应该接近零或为零。这样做可能有正当的理由,但我敢说,99.9% 的情况下,这是一种反优化行为。
正常 I/O 将转到缓冲区缓存,脏页将由内核线程异步写出。带宽 = RAM 速度,延迟 = RAM 延迟(另外,可能还会有几微秒的页面错误)。当
系统耗尽物理 RAM 时,您将被阻止(显然),没有其他办法。当没有剩余的页面可以写入时,您将不得不等待,直到一些页面被释放。没有其他办法。
但是,根据定义,在您的特定情况下,耗尽 RAM 不太可能(或不可能)发生。否则,如果确实有可能耗尽 RAM,那么创建 tmpfs 的想法从一开始就很愚蠢。
tmpfs 的 I/O 将转到...缓冲区缓存。是的,现在它以不同的名称运行,但实际上由于统一的 VM 系统,它完全相同。因此带宽和延迟完全相同(由于文件系统的细微差别可能略有不同,因此可能存在 1% 的差异)。是的,没有发生写回。但谁在乎呢,看看它会如何异步发生。相反,现在您无法享受有人在后台释放脏页的便利,因此如果可能的话,达到上限的可能性实际上更高。
当系统物理 RAM 耗尽时,您仍然只能写入内存中映射的页面,因此理论上您应该能够更快地完成此操作。然而,实际上,物理 RAM 仍然只有这么多,而您已经用完了!当然,您的 tmpfs 中可能还有空间,但出于某种原因,您还否则需要写入内存页,而且没有剩余的内存页。
所以内核必须做某物保持系统运行。它必须不知何故重新安排资源以缓解问题(可能交换 docker 进程和整个容器?!)。内核会尽力而为,但它不能施展魔法,它必须某物,并且它的选择是有限的。更糟糕的是,你故意拿走了大量的页面,而这些页面本来可以自由地用于任何目的(包括必须立即满足的请求)。