パイプとリダイレクト速度、「pv」とUUOC

パイプとリダイレクト速度、「pv」とUUOC

ランダムゴミを生成し、pv次のように出力をパイピングして速度を比較するさまざまな方法をテストしています。

$ cmd | pv -s "$size" -S > /dev/null

私はまた、「リファレンスリファレンス」が欲しかったので、cat最速のソースで最速の「ジェネレータ」を測定しました/dev/zero

$ cat /dev/zero | pv -s 100G -S > /dev/null
 100GiB 0:00:33 [2,98GiB/s] [=============================>] 100%   

3GB/秒、特に次のような場合は非常に印象的です。~70MB私はから来ました/dev/urandom

/dev/zeroしかし、特別な場合には必要ありませんcat!ただ楽しんでこの教科書を消しました。ウルムチ大学:

$ < /dev/zero pv -s 100G -S > /dev/null
 100GiB 0:00:10 [9,98GiB/s] [=============================>] 100%            

何? ? ?ほぼ10GB/秒?解体catとパイプラインはどのように比較されますか?三回スピード?たとえば、遅いソースを使用している場合、/dev/urandom違いは無視できます。魔法を呼ぶのでしょうかpv?だからテストしました:

$ dd if=/dev/zero iflag=count_bytes count=200G of=/dev/null status=progress
205392969728 bytes (205 GB, 191 GiB) copied, 16 s, 12,8 GB/s

12.8GB/秒!パイプを使うのとほぼ同じでpv、パイプを使うよりも4倍速いです。

あなた自身のせいですかcat?パイプはリダイレクトとは大きく異なりますか?最後に、両方ともpvasに移動しますstdin。そうですか?この大きな違いを何で説明できますか?

答え1

秘訣は、2つのプロセスを使用することです。

同じcat | pvcat読み取りと書き込み、pv読み取りと書き込み、両方のプロセスを実行する必要があります。

$ perf stat sh -c 'cat /dev/zero | pv -s 100G -S > /dev/null'
 100GiB 0:00:26 [3.72GiB/s] [====================================================================================>] 100%            

 Performance counter stats for 'sh -c cat /dev/zero | pv -s 100G -S > /dev/null':

         34,048.63 msec task-clock                #    1.267 CPUs utilized          
         1,676,706      context-switches          #    0.049 M/sec                  
             3,678      cpu-migrations            #    0.108 K/sec                  
               304      page-faults               #    0.009 K/sec                  
   119,270,941,758      cycles                    #    3.503 GHz                      (74.89%)
   137,822,862,590      instructions              #    1.16  insn per cycle           (74.94%)
    32,379,369,104      branches                  #  950.974 M/sec                    (75.14%)
       216,658,446      branch-misses             #    0.67% of all branches          (75.04%)

      26.865741948 seconds time elapsed

       1.257950000 seconds user
      38.893870000 seconds sys

専用pvpv読み取り、書き込みのみ可能、コンテキスト切り替えは不要(またはほとんどありません):

$ perf stat sh -c '< /dev/zero pv -s 100G -S > /dev/null'
 100GiB 0:00:07 [13.3GiB/s] [====================================================================================>] 100%            

 Performance counter stats for 'sh -c < /dev/zero pv -s 100G -S > /dev/null':

          7,501.68 msec task-clock                #    1.000 CPUs utilized          
                37      context-switches          #    0.005 K/sec                  
                 0      cpu-migrations            #    0.000 K/sec                  
               198      page-faults               #    0.026 K/sec                  
    27,916,420,023      cycles                    #    3.721 GHz                      (75.00%)
    62,787,377,126      instructions              #    2.25  insn per cycle           (74.99%)
    15,361,951,954      branches                  # 2047.801 M/sec                    (75.03%)
        51,741,595      branch-misses             #    0.34% of all branches          (74.98%)

       7.505304560 seconds time elapsed

       1.768600000 seconds user
       5.733786000 seconds sys

いくつかの並列処理(「1.267 CPUを使用」)がありますが、コンテキスト切り替え数の大きな違いを補償するものではありません。

データパスを考慮すると、状況はおそらくはるかに悪いでしょう。最初の場合、データは/dev/zeroカーネル()からcatカーネル(パイプの場合)に戻り、その後pvカーネル(/dev/null)に流れるように見えます。 2番目のケースでは、データはコアからコアに流れ、pv再びコアに流れます。しかし、pv最初のケースではspliceカーネル所有メモリを通過しないようにパイプからデータをコピーします。

関連情報