ddパイプラインのgunzipが遅くなるのはなぜですか?

ddパイプラインのgunzipが遅くなるのはなぜですか?

私のコマンド:

gunzip -c serial2udp.image.gz |
sudo dd of=/dev/mmcblk0 conv=fsync,notrunc status=progress bs=4M

私の結果:

15930949632 bytes (16 GB, 15 GiB) copied, 1049 s, 15.2 MB/s    

0+331128 records in
0+331128 records out
15931539456 bytes (16 GB, 15 GiB) copied, 1995.2 s, 8.0 MB/s

カード:SanDisk Ultra 32GB MicroSDHC Class 10 UHSメモリーカード速度最大30MB / s
リリース:16.0.4 xenial(xfceを含む)
カーネルバージョン:4.13.0.37-generic

私が読んだ内容によると、17分ほどかかるのが合理的だと思います。ブロックサイズを変更しても大きな違いはないようです(bs = 100Mはまだ同じタイムスタンプでこの動作を示します)。アップデートが中断されてから16分間完了したレポートが生成されないのはなぜですか?

iotopはmmcqd / 0が現在(99%IO)バックグラウンドでまだ実行されていることを知っているので、どこかに最後の5MBを保持するキャッシュがあると思いますが、fsyncはそのようなことが起こらないようにする必要があると思います。iotopはddを示します。現時点では交差点もありません。 ctrl-cはほとんど役に立たない。書き込み後にドライブを損傷したくありません。

答え1

最後の5MBを保持するキャッシュがどこかにあるようですが、fsyncがこれが起こらないようにしなければならないと思います。

conv=fsyncfsyncすべてのデータが作成された後に呼び出され、すべてのキャッシュを書き換えることを示します。dd最後にぶら下がるのがまさにそのことです。

出力ファイルが入力ファイルより遅い場合、記録されたデータがddキャッシュに蓄積される可能性があります。カーネルキャッシュは時々システムRAMのかなりの部分を満たすことができる。これは非常に誤った進捗情報を生成します。 「最後の5MB」はdd進行状況を示すアーティファクトだけです。

システムが約8GB(書き込みデータ16GBの半分)をキャッシュしている場合は、約32GBのRAMがあるか、いくつかのカーネルオプションを調整する必要があると思います。以下のlwn.netリンクを参照してください。同意します。 15分間進行状況情報を受け取ることができないのはかなり残念です。

他のコマンドを使用できますdd。より正確な進捗状況を表示したい場合は、ddより複雑さを受け入れる必要があります。現実は私とは異なるかもしれませんが、次のことがあなたのパフォーマンスを低下させないことを願っています。

gunzip -c serial2udp.image.gz |
dd iflag=fullblock bs=4M |
sudo dd iflag=fullblock oflag=direct conv=fsync status=progress bs=4M of=/dev/mmcblk0
  • oflag=direct iflag=fullblockカーネルキャッシュは完全にバイパスされるので、スタックを積み重ねないでください。
  • iflag=fullblockAFAIKは、このようなコマンドに必要です(たとえば、パイプから読み込み、直接IOを使用して書き込むため)。不足の影響はfullblock別の不幸な合併症ですdd。このサイトのいくつかの投稿は、それを使用して常に他のコマンドを使用することを好むべきであると主張しています。しかし、直接または同期IOを実行する他の方法を見つけることは困難です。
  • conv=fsync引き続き使用する必要があります。返信してください。装備隠れ家。
  • ディスクへの書き込みと並列に解凍された出力をバッファリングするために、後にdd追加を追加しました。これはパフォーマンスを複雑にするか少し複雑にするgunzip問題の1つです。通常のIO(非直接、非同期)にはすでにカーネルキャッシュによってバッファされているので、これは必要ありません。 4M書き込みストレージキャッシュを持つハードドライブに書き込む場合、追加のバッファも必要ないかもしれませんが、SDカードにはそれほど多くのバッファがないと思います。oflag=directoflag=sync

使用することもできますoflag=direct,sync(不要conv=fsync)。奇妙な出力デバイスがある場合は、良い進捗情報を提供するのに役立ちます。数百メガバイトのキャッシュ。しかし、一般的に私はoflag=syncこれがパフォーマンスに潜在的な妨害になると思います。

2013年の記事がありますねhttps://lwn.net/Articles/572911/それはあなたのような数分の遅れに言及します。多くの人は、数分間書き込みデータをキャッシュするこの機能が望ましくないと思います。問題は、キャッシュサイズの制限が高速デバイスと低速デバイスに無差別に適用されることです。デバイスの速度はデータの位置に依存するため、カーネルがデバイスの速度を測定するのは容易ではありません。たとえば、キャッシュされた書き込みが任意の場所に分散されている場合、ハードドライブが書き込みヘッドを繰り返し移動するのに時間がかかります。

更新が中断される理由

これはfsync()、フルスコープに適用される単一のシステムコールです。文書機器。完了するまでステータス更新は返されません。

答え2

を使いたいですfullblocknotruncデバイスファイルには影響しません。

dd of=/dev/mmcblk0 iflag=fullblock status=progress bs=4M

答え3

答え自体ではありませんが、診断に近いです。パイプビューユーティリティの使用pv各パイプラインの流量の変化を確認し、例えば:

pv -c -N raw serial2udp.image.gz |
gunzip |
pv -c -N uncompressed |
sudo dd of=/dev/mmcblk0 conv=fsync,notrunc status=progress bs=4M

仮定:

  1. 最後の部分で遅い場合は、.gzファイルが最後の部分で最も圧縮されているか、gunzipより多くの作業が必要になる可能性があります。
  2. もう1つの可能性は、書き込みメディア自体がデザインの性質や不良/制限ブロックのために特定の部分で遅くなることです。非破壊的な読み取り/書き込みテストは、次の方法で実行できます。badblocks -nv /dev/mmcblk0

関連情報