名前付きパイプがファイルに書き込むのと同じくらい遅いのはなぜですか?

名前付きパイプがファイルに書き込むのと同じくらい遅いのはなぜですか?

一方向プロセス間の通信を簡素化するために、名前付きパイプがどのように機能するかを理解したいと思います。データを循環バッファにコピーすると、わずかなオーバーヘッドが発生すると予想されます。これはRAMに保存されていると仮定しているため、パイプがファイルに書き込むよりもはるかに高速になると予想されます(RAMはディスクよりも数倍速いためです)。 。

代わりに、名前付きパイプ(または匿名パイプ)がファイルと速度がほぼ同じであることを発見しました。これは、Ubuntu Linuxを実行する通常のディスクドライブ(ソリッドステートではない)を備えた3GHzデスクトップです。以下は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ベースのバッファの代わりにファイルベースのバッファを介してパイプを実行する」というスイッチがあります。これを変更できますか?カーネルオプションですか、それともシェル変数ですか?

別の説明:500は単なるパイプであり、930は実際に記録されているので、ディスク出力が500から930マイクロ秒の間にジャンプすると仮定します。これにより、パイプラインの500〜640はどちらの場合も同じです。しかし、これらの説明を考慮すると、パイピングと実際にディスクに書き込むこととの間になぜ2倍しかありませんか? RAMディスクについて説明するウェブサイトRAMディスクはハードディスクより50~200倍速いそうです。

答え1

ファイルを使用すると実際にディスクにアクセスしないため、パフォーマンス上の利点は見られません。データはディスクに移動していますが、実行スレッドはディスクに到達するのを待つ必要はありません。実際にはしないでくださいよりディスクに衝撃を与えると速度が失われます。

どれだけ遅いかを確認するためにディスク操作が完了するのを待つには、次のように呼び出します。sync()(これがPythonのバージョンによってどのように変わるかについては、以下を参照してください。)ここ) - ディスクがファイルを書き込むために数回スキャンするようにするのに数万マイクロ秒を費やします(RAIDコントローラなどの一種の高速書き込みキャッシュがないとします)。

関連情報