web-dev-qa-db-ja.com

なぜlinuxcpコマンドはディスクIOを消費しないのですか?

os:centos7

テストファイル:a.txt 1.2G

監視コマンド:iostat -xdm 1

The first scene:
cp a.txt b.txt        #b.txt is not exist

enter image description here

The second scene: 
cp a.txt b.txt        #b.txt is exist

enter image description here

最初のシーンがIOを消費しないのに、2番目のシーンがIOを消費するのはなぜですか?

6
tairyao

最初のcp操作中にデータがディスクにフラッシュされなかったが、2番目の操作中にデータがフラッシュされた可能性があります。

vm.dirty_background_bytesを1048576(1 MiB)などの小さな値に設定して、これが当てはまるかどうかを確認してください。 sysctl -w vm.dirty_background_bytes=1048576を実行すると、最初のcpシナリオでI/Oが表示されます。

何が起きてる?

同期および/または直接I/Oの場合を除いて、ディスクへの書き込みは、しきい値に達するまでメモリにバッファリングされます。しきい値に達すると、バックグラウンドでディスクへのフラッシュが開始されます。このしきい値には正式な名前はありませんが、vm.dirty_background_bytesvm.dirty_background_ratioによって制御されるため、「ダーティバックグラウンドしきい値」と呼びます。 カーネルドキュメントから

vm.dirty_background_bytes

バックグラウンドカーネルフラッシャースレッドがライトバックを開始するダーティメモリの量が含まれます。

注:dirty_background_bytesdirty_background_ratioに対応します。一度に指定できるのはそのうちの1つだけです。一方のsysctlが書き込まれると、ダーティメモリ制限を評価するためにすぐに考慮され、もう一方は読み取られると0として表示されます。

dirty_background_ratio

空きページと再利用可能なページを含む使用可能な合計メモリのパーセンテージとして、バックグラウンドカーネルフラッシャースレッドがダーティデータの書き込みを開始するページ数が含まれます。

使用可能なメモリの合計は、システムメモリの合計と同じではありません。

vm.dirty_bytesおよびvm.dirty_ratio

これを超えて、2番目のしきい値があります。まあ、しきい値よりも制限があり、それはvm.dirty_bytesvm.dirty_ratioによって制御されます。繰り返しになりますが、正式な名前がないため、「ダーティリミット」と呼びます。十分なデータが「書き込まれる」が、基になるブロックデバイスにコミットされない場合、writeをさらに試行すると、書き込みI/Oが完了するまで待機する必要があります。 (彼らが待機しなければならないデータの正確な詳細は私にはわかりません。I/ Oスケジューラの機能である可能性があります。わかりません。)

どうして?

ディスクが遅い。スピニングRust特にそうなので、ディスク上のR/Wヘッドが読み取り要求を満たすために移動している間、読み取り要求が完了して書き込み要求を開始できるまで、書き込み要求を処理することはできません。 (およびその逆)

効率

これが、書き込み要求をメモリにバッファリングし、読み取ったデータをキャッシュする理由です。作業を低速のディスクから高速のメモリに移動します。最終的にデータをディスクにコミットするとき、処理するデータの量が十分にあるので、シーク時間を最小限に抑える方法でデータを書き込もうとすることができます。 (SSDを使用している場合は、ディスクシーク時間の概念をSSDブロックの再フラッシュに置き換えます。再フラッシュはSSDの寿命を消費し、遅い操作です。SSDは、さまざまな程度の成功を収めて、独自の書き込みで非表示にしようとします。キャッシング。)

カーネルがvm.dirty_background_bytesおよびvm.dirty_background_ratioを使用してデータをディスクに書き込もうとする前に、バッファリングされるデータの量を調整できます。

バッファリングされた書き込みデータが多すぎます!

書き込んでいるデータの量がディスクに到達する速さに対して多すぎる場合、最終的にはすべてのシステムメモリを消費します。まず、読み取りキャッシュがなくなります。つまり、メモリから処理される読み取り要求が少なくなり、ディスクから処理する必要があるため、書き込みがさらに遅くなります。それでも書き込みプレッシャーが解消されない場合は、最終的にはメモリ割り当てのように、書き込みキャッシュが解放されるのを待つ必要があり、それはさらに混乱を招きます。

つまり、vm.dirty_bytes(およびvm.dirty_ratio)があります。 「ちょっと待ってください。これがさらに悪化する前に、実際にディスクにデータを取得する時が来ました」と言うことができます。

まだデータが多すぎる

ただし、I/Oをハードストップすることは非常に混乱を招きます。ディスクは読み取りプロセスの観点からすでに低速であり、そのデータがフラッシュされるまでに数秒から数分かかる場合があります。 vm.dirty_bytesのデフォルトの20を検討してください。16GiBのRAMでスワップがないシステムの場合、3.4GiBのデータが取得されるのを待つ間にI/Oがブロックされることがあります。ディスクにフラッシュされました。128GiBのRAMを搭載したサーバーでは、27.5GiBのデータを待機している間、サービスがタイムアウトになります。

したがって、vm.dirty_bytes(または必要に応じてvm.dirty_ratio)をかなり低く保つと便利です。これにより、このハードしきい値をヒットすると、サービスへの影響を最小限に抑えます。

良い値は何ですか?

これらの調整機能を使用すると、スループットとレイテンシーの間で常にトレードを行うことができます。バッファリングが多すぎると、スループットは向上しますが、レイテンシはひどくなります。バッファリングが少なすぎると、スループットはひどくなりますが、レイテンシは大きくなります。

ディスクが1つしかないワークステーションやラップトップでは、vm.dirty_background_bytesを約1MiBに設定し、vm.dirty_bytesを8MiBから16MiBの間に設定するのが好きです。シングルユーザーシステムで16MiBを超えるスループットのメリットを見つけることはめったにありませんが、Webブラウザーのデータストアなどの同期ワークロードでは、レイテンシーのハングアップがかなり悪化する可能性があります。

ストライプパリティ配列を使用する場合は、配列のストライプ幅の倍数がvm.dirty_background_bytesの適切な開始値であることがわかります。パリティの更新中に読み取り/更新/書き込みシーケンスを実行する必要が生じる可能性を減らし、アレイのスループットを向上させます。

vm.dirty_bytesの場合、サービスが受ける可能性のある遅延の量によって異なります。私自身、ブロックデバイスの理論上のスループットを計算し、それを使用して100ミリ秒程度で移動できるデータ量を計算し、それに応じてvm.dirty_bytesを設定するのが好きです。 100msの遅延は非常に大きいですが、(私の環境では)壊滅的ではありません。

ただし、これはすべて環境によって異なります。これらは、自分に適したものを見つけるための出発点にすぎません。

7
Michael Mol