ハードウェアリソースにあふれないオンザフライストリーム圧縮


23

200 GBの空きディスク容量、16 GBのRAM(そのうち約1 GBはデスクトップとカーネルが占有)、6 GBのスワップがあります。

240 GBの外付けSSDがあり、70 GBが使用され1が残り、残りはディスクにバックアップする必要があります。

通常、dd if=/dev/sdb of=Desktop/disk.img最初にディスクを使用してから圧縮しますが、圧縮ステップにより空き領域が押しつぶされる場合でも、イメージを最初に作成することはオプションではありません。最終アーカイブはディスクに簡単に収まります。

ddデフォルトでSTDOUTに書き込みgzip、STDINから読み取ることができるため、理論的にはを書き込むことができますがdd if=/dev/sdb | gzip -9 -gzipバイトddを生成するよりもバイトの読み取りにかなり時間がかかります。

からman pipe

パイプの書き込み側に書き込まれたデータは、パイプの読み取り側から読み取られるまでカーネルによってバッファリングされます。

|実際のパイプのように視覚化します。1つのアプリケーションがデータを押し込み、もう1つのアプリケーションがパイプのキューからデータをできるだけ早く取り出します。

左側のプログラムがパイプの反対側が処理を期待できるよりも多くのデータをより速く書き込むとどうなりますか?それは極端なメモリまたはスワップの使用を引き起こしますか、またはカーネルはディスク上にFIFOを作成しようとし、それによりディスクをいっぱいにしますか?それともSIGPIPE Broken pipe、バッファが大きすぎると失敗しますか?

基本的に、これは2つの質問に要約されます。

  1. 一度に読み取られるよりも多くのデータをパイプに押し込むことの意味と結果は何ですか?
  2. 圧縮されていないデータストリーム全体をディスクに配置せずに、データストリームをディスクに圧縮する信頼できる方法は何ですか?

注1:最初の70個の使用済みGBを正確にコピーすることはできません。断片化など、コンテンツ全体を完全に維持する必要があるため、動作中のシステムまたはファイルシステムを取得します。


ユーザーディレクトリだけでなく、インストールされている非標準ソフトウェアのリストではなく、なぜそのようなファイルシステム全体をバックアップするのですか?
-jamesqf

5
@jamesqf例:復元する方がはるかに簡単だから
...-逸脱したファン

4
@jamesqfその後、ブートセクターとスワップパーティションも取得するため、10億の迷惑なファイルを作成する代わりにディスクを正確に再作成できます。

3
ランダムなヒント:のlzop代わりに調べてくださいgzip。圧縮率がわずかに低いだけで、はるかに高速に圧縮されます。圧縮速度が本当のボトルネックになりかねないディスクイメージに理想的です。
-marcelm

1
「左側のプログラムが、パイプの反対側がそれを処理することを期待できるよりも多くのデータをより速く書き込む場合はどうなりますか?」カーネルは、パイプに空きができるまで書き込みプロセスをスリープさせます。
タビアンバーンズ

回答:


16

技術的には必要ありませんdd

gzip < /dev/drive > drive.img.gz

あなたが使用を行う場合dd、あなたはいつものように、デフォルトのブロックサイズより大きくして行くべきdd bs=1Mか、システムコールの地獄に苦しむ(ddそれは以降のデフォルトのブロックサイズは、512バイトであるread()Sとwrite()だsの4096あたりのシステムコールをMiBあまりにも多くのオーバーヘッド、)。

gzip -9表示するものがほとんどない、より多くのCPUを使用します。gzip速度が低下している場合は、圧縮レベルを下げるか、別の(高速の)圧縮方法を使用します。

ddイメージの代わりにファイルベースのバックアップを行う場合、圧縮するかどうかを決定するロジックを使用できます(さまざまな種類のファイルに対して圧縮する意味はありません)。dartaralternative`)は、そうするためのオプションがある1つの例です。

空き領域がゼロの場合(TRIM後に確実にゼロを返すSSDでfstrimあり、キャッシュを実行およびドロップした場合)ddconv=sparseフラグを使用して、ゼロ領域にゼロディスク領域を使用する非圧縮のループマウント可能なスパースイメージを作成することもできます。スパースファイルをサポートするファイルシステムで画像ファイルをバックアップする必要があります。

また、一部のファイルシステムでは、使用領域のみをイメージ化できるプログラムが存在します。


1
「ddを使用する場合は、常にデフォルトのブロックサイズより大きくする必要がありますdd bs=1M -可能ですが、あまり期待しないでください。私のPCでは、dd512バイトブロックで約2GB / sを実行します。それがボトルネックになることはありません。gzipなります。
-marcelm

@marcelm私たちは、人々がどんな種類の機械を使っているのか決して知りません。あなたがいる場合はdd2ギガバイトを行く/ 512バイトブロックでね、それはプロセスで最大うち1つのCPUコアを100%しなかった場合、私は驚かれることでしょう。ボックスがクアッドコアで、とにかくアイドル状態にある場合、違いに気付かないかもしれません。ただし、他の人はまだそうしています。
frostschutz

9
ため息。ddブロックサイズが記載されるたびに、人々はピクピクします。gzipCPUを集中的に使用することも私の答えの一部でした。申し訳ありませんが、「無視できる」ことに同意しません。ギグあたり1〜2秒しか追加されない場合がありますgzip -9(ただし、数百のギグを処理する場合は数分になります)が、ギグlzop -1あたり1秒対ギグあたり4秒というアドバイスがあります。ジャガイモ(シングルコア仮想サーバー)でテスト済み。適切なブロックサイズを追加してddも、費用はかからず、マイナス面はありません。ピックしないでください。早くやれよ。ymmv
frostschutz

19

dd一度に1ブロックずつデータを読み書きしますが、未処理のブロックは1つだけです。そう

valgrind dd if=/dev/zero status=progress of=/dev/null bs=1M

dd約1MBのメモリを使用することを示しています。ブロックサイズをいじってドロップするとvalgrinddd速度への影響を確認できます。

にパイプするとgzip、の速度ddに合わせて速度が低下しgzipます。そのメモリ使用量は増加しません。また、(カーネルは除いて、それを行う方法を知っていないディスクにバッファを保存するためのカーネルを引き起こすん経由スワップ)。パイプの破損は、パイプの一方の端が死んだときにのみ発生します。signal(7)およびwrite(2)を参照してください。

かくして

dd if=... iconv=fullblock bs=1M | gzip -9 > ...

あなたがしたいことをする安全な方法です。

パイピングの際、読み取りプロセスが追いついていない場合、書き込みプロセスはカーネルによってブロックされてしまいます。これを実行するには、次を実行します

strace dd if=/dev/zero bs=1M | (sleep 60; cat > /dev/null)

dd1MB を読み取り、実行write()中に1分間待機するを発行しsleepます。これがパイプの両側のバランスです。書き込みプロセスが速すぎるとカーネルは書き込みをブロックし、読み取りプロセスが速すぎると読み取りをブロックします。


1
それはいいね。の速度ddに合わせて速度を落とすことがわかっているのはどのメカニズムgzipですか?カーネルのように自動的に行われますか、または出力ファイル記述子に関するメタデータから計算しますか?

9
@cat自動です。データをパイプに入れるためのdd呼び出しwrite()write()実際にカーネルに制御を転送して、パイプメモリを操作できるようにします。カーネルはパイプがいっぱいであると認識すると、パイプに十分なスペースができるまで待機(「ブロック」)します。その場合にのみ、write()呼び出しが終了し、コントロールがに戻りdd、パイプにデータが再び書き込まれます。
-marcelm

9

パフォーマンス以外にマイナスの影響はありません。パイプには通常64Kのバッファーがあり、その後、パイプへの書き込みは、gzipさらにデータを読み取るまでブロックされます。


8

それがどのように機能するかについての実際の質問に答える:「左側のプログラムがパイプの反対側がそれを処理することを期待できるよりも速くより多くのデータを書き込む場合はどうでしょうか?」

これは起こりません。パイプには、かなり小さく制限されたサイズのバッファーがあります。パイプバッファーの大きさを参照してください

パイプバッファがいっぱいになると、送信プログラムはブロックします。書き込み呼び出しを行うと、カーネルはデータがバッファに書き込まれるまでプログラムに制御を返しません。これにより、読み取りプログラムにバッファーを空にするCPU時間を与えます。


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