CPUとハードドライブのパフォーマンスが限界に達していないにもかかわらず、gzipが遅いのはなぜですか?


14

それぞれに20 GBのJSONファイルをいくつか圧縮しgzipます。

gzip file1.json

これには、1つの完全なCPUコアが必要です。

処理atop速度は約25 MB /秒(でチェックイン)、ハードドライブは125 MB /秒を読み取ることができ、3つの空きプロセッサコアがあるので、複数のファイルを並列に圧縮すると速度が向上すると予想しています。だから私は他の端末で実行します:

gzip file2.json
gzip file3.json
gzip file4.json

驚いたことに、私のスループットは向上しません。CPUは各コアで約25%であり、私のHDはまだ25 MB /秒でしか読み取れません。

なぜ、どのように対処するのですか?

回答:


17

私はそれを見つけました:

その理由は、gzip(最近のCPU速度とHDシーク速度の観点から)非常に低いバッファーサイズで動作するためです。

入力ファイルから数KBを読み取り、圧縮して、出力ファイルにフラッシュします。これにはハードドライブシークが必要なため、1秒あたりの操作数はわずかです。

私のパフォーマンスがスケーリングしなかった理由は、すでに1人gzipが狂ったように求めていたからです。


私はunix bufferユーティリティを使用してこれを回避しました:

buffer -s 100000 -m 10000000 -p 100 < file1.json | gzip > file1.json.gz

大量の入力をgzipに送信する前にバッファリングすることにより、小さなシークの数を劇的に減らすことができます。オプション:

  • -sそして-m、バッファのサイズを指定することです(私は信じている、それは確かKBである、ではありません)
  • -p 100 バッファーが100%満たされたときにのみ、データがgzipに渡されることを確認します

これらのうち4つを並行して実行すると、期待どおりに4 * 25 MB / sのスループットが得られます。


なぜgzipがバッファーサイズを増やすことができないのか、私はまだ疑問に思っています。

編集:私はいくつかの圧縮プログラムの動作を試しました:

  • bzip2 より強力な/より多くのCPU集中圧縮により、2 MB /秒のみを処理します
  • lzop より大きなバッファーを許可しているようです:コアあたり70 MB /秒、2つのコアでオーバーシークせずにHDを最大化できます

dd同じことができますか?
Simon Kuang 2014年

@SimonKuang はいdd、そのbs=オプションで同じことができると思います。
nh2

興味深い偶然のように聞こえますが、単一のファイルの場合、ブロックサイズはたまたま単一のCPUコアとドライブのIOPSの両方を完全に利用しています。
Dave L.

3

6.172のMIT OpenCoursewareの最初の5つほどの講義「ソフトウェアシステムのパフォーマンスエンジニアリング」を見た後、Linuxパフォーマンスアナライザー「perf」を適度に大きなテストファイルで実行しました。結果は、1つの命令が前の命令の結果を待たなければならないパイプラインストールを示しているように見えます。

       │         while (lookahead != 0) {                                                                
       │             /* Insert the string window[strstart .. strstart+2] in the                          
       │              * dictionary, and set hash_head to the head of the hash chain:                     
       │              */                                                                                 
       │             INSERT_STRING(strstart, hash_head);                                                 
  2.07 │       movzbl 0x8096d82(%edx),%eax                                                               
  3.99 │       mov    %edx,%ebp                                                                          
       │       shl    $0x5,%ecx                                                                          
  0.03 │       and    $0x7fff,%ebp                                                                       
  1.94 │       xor    %ecx,%eax                                                                          
  1.43 │       and    $0x7fff,%eax                                                                       
  2.01 │       mov    %eax,0x805e588                                                                     
  2.40 │       add    $0x8000,%eax                                                                      
  0.88 │       movzwl 0x8062140(%eax,%eax,1),%ecx                                                        
 23.79 │       movzwl %cx,%edi                                                                           
       │             /* Find the longest match, discarding those <= prev_length.  

最後から2番目の命令はへのコピーで%ecxあり、最後の命令は、%cxデータが使用できるようになるまでレジスタが待機する(パイプラインを停止する)必要があります。このパイプラインストールは、包含ループを保持します。

これは、いくつかの本当にあいまいな「古い」Cプログラミングスタイルの結果です。


1

マルチコア/ハイパースレッディングCPUでさらに別のレベルの速度に引き上げる可能性があるヒント:
(Ubuntuを想定)

sudo apt-get install moreutils

moreutilsには、とりわけ「gnuパラレル」が含まれています。これには、CPUをより多く使用するのに役立つ多くのオプションがあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.