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

Jim*_*ski 20 fifo

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

相反,我发现命名管道(或匿名管道)与文件的速度大致相同。这是在带有普通磁盘驱动器(非固态)、运行 Ubuntu Linux 的 3 GHz 桌面上。这是一个简化的 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)))
Run Code Online (Sandbox Code Playgroud)

管道直通/dev/null

python test.py > /dev/null
Run Code Online (Sandbox Code Playgroud)

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

管道到文件:

python test.py > /tmp/testout.txt
Run Code Online (Sandbox Code Playgroud)

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

然后命名管道:

mkfifo testpipe
cat testpipe > /dev/null &
python test.py > testpipe
Run Code Online (Sandbox Code Playgroud)

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

python test.py | cat > /dev/null
Run Code Online (Sandbox Code Playgroud)

也产生 650 微秒(常数)。

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

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

小智 33

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

如果您想等待磁盘操作完成以查看速度变慢了多少,请调用 a sync()(如何根据您的 Python 版本而变化,请参见此处)-您将看到数万微秒仅用于您的磁盘寻求几次以将文件写出(假设它没有像 RAID 控制器那样的某种快速写入缓存)。

  • @EEAA 所有 SSD,一直。 (5认同)