为什么命名管道与写入文件一样慢?

为什么命名管道与写入文件一样慢?

我试图了解命名管道的工作原理,以便我可以简化单向进程间通信。我预计由于将数据复制到循环缓冲区中会产生一些开销,我认为这些数据存储在 RAM 中,因此我预计管道比写入文件要快得多(因为 RAM 比磁盘快几个数量级)。

相反,我发现命名管道(或匿名管道)的速度与文件大致相同。这是一个带有普通磁盘驱动器(非固态)的 3 GHz 桌面,运行 Ubuntu Linux。这是一个用 Python 编写的简化测试程序:

import sys
import time
import random

megabyte = "".join(random.choice("abcdefghijklmnopqrstuvwxyz") for x in range(1024**2))

while True:
    before = time.time()
    sys.stdout.write(megabyte)
    after = time.time()
    sys.stderr.write("{} microseconds\n".format(1e6 * (after - before)))

管道直达/dev/null

python test.py > /dev/null

每兆字节产生 2.1 微秒(常数)。

通过管道传输到文件:

python test.py > /tmp/testout.txt

在 500 微秒和 930 微秒之间跳跃(随着文件变大,较大的值变得更常见——大概是在寻找磁盘空间)。

然后是命名管道:

mkfifo testpipe
cat testpipe > /dev/null &
python test.py > testpipe

产生 640 微秒(常数)和一个未命名的管道:

python test.py | cat > /dev/null

还产生 650 微秒(常数)。

谁能解释为什么管道的速度更像文件的速度而不是/dev/null速度?我可能在某处有一个开关,上面写着“通过基于文件的缓冲区运行管道,而不是基于 RAM 的缓冲区”,我可以更改该开关吗?它可能是内核选项或 shell 变量吗?

另一种解释:假设磁盘输出在 500 到 930 微秒之间跳跃,因为 500 只是管道传输,而 930 实际上正在写入。那么两种情况下管道的 500 ~ 640 是等效的。然而,根据这种解释,为什么管道传输和实际写入磁盘之间只有两倍的系数? 谈论 RAM 磁盘的网站据说 RAM 磁盘比硬盘快 50-200 倍。

答案1

您没有看到任何性能优势,因为在使用文件时您实际上并没有访问磁盘 - 数据正在发送到磁盘的途中,但您的执行线程不需要等待它到达那里,所以您实际上不看到撞击磁盘的速度损失。

如果您想等待磁盘操作完成以查看速度慢了多少,请调用 a sync()(如何根据您的 python 版本而变化,请参阅这里) - 您将花费数万微秒的时间来让您的磁盘查找几次以将文件写出(假设它没有像 RAID 控制器那样的某种快速写入缓存)。

相关内容