大きなファイルのバックグラウンド書き込みを行うプロセスがあります。他のプロセスへの影響を最小限に抑えてください。
これは、SLES11SP4で実現されたテストです。サーバーには大容量のメモリがあり、4GBのダーティページを作成できます。
> dd if=/dev/zero of=todel bs=1048576 count=4096
4096+0 records in
4096+0 records out
4294967296 bytes (4.3 GB) copied, 3.72657 s, 1.2 GB/s
> dd if=/dev/zero of=zer oflag=sync bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 16.6997 s, 0.0 kB/s
real 0m16.701s
user 0m0.000s
sys 0m0.000s
> grep Dirty /proc/meminfo
Dirty: 4199704 kB
これはこれまでの私の調査です:
これが私の質問です:
も参照してください
https://www.novell.com/support/kb/doc.php?id=7010287
Linuxバックグラウンドフラッシュを制限する(ダーティページ)
http://yarchive.net/comp/linux/dirty_limits.html
編集:
同じデバイスの下にext2ファイルシステムがあります。このデバイスでは、フリーズはまったくありません!発生する唯一のパフォーマンスへの影響は、ダーティページのフラッシュ中に発生します。この場合、同期呼び出しには最大0.3秒かかる可能性があり、ext3ファイルシステムで発生するものとはかけ離れています。
EDIT2:
@Matthew Ifeのコメントに続いて、O_TRUNCなしでファイルを開く同期書き込みを実行しようとしましたが、結果は信じられません。
> dd if=/dev/zero of=zer oflag=sync bs=512 count=1
> dd if=/dev/zero of=todel bs=1048576 count=4096
> dd if=/dev/zero of=zer oflag=sync bs=512 count=1 conv=notrunc
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000185427 s, 2.8 MB/s
ddはパラメータを使用してファイルを開いていました:
open("zer", O_WRONLY|O_CREAT|O_TRUNC|O_SYNC, 0666) = 3
notruncオプションで変更すると、
open("zer", O_WRONLY|O_CREAT|O_SYNC, 0666) = 3
同期書き込みは瞬時に完了します!
私のユースケースでは完全に満足できるものではありません(私は この方法で でmsyncを実行しています。しかし、writeとmsyncが異なる方法で実行していることを追跡できるようになりました!
最終編集:これに当たったなんて信じられない: https://www.novell.com/support/kb/doc.php?id=70161
実際、SLES11の下では、ddはファイルを次のように開いています。
open("zer", O_WRONLY|O_CREAT|O_DSYNC, 0666) = 3
およびO_DSYNC == O_SYNC!
結論:
私のユースケースでは、おそらく使用する必要があります
dd if=/dev/zero of=zer oflag=dsync bs=512 count=1 conv=notrunc
SLES11では、straceが何を言っていても、oflag = syncを実行すると実際にはoflag = dsyncが実行されます。
結果を知りたいと思うことがいくつかあります。
最初にfallocate
を使用して大きなファイルを作成し、次に書き込みます。
Dirty_background_bytesをはるかに低く設定し(たとえば1GiB)、スケジューラーとしてCFQを使用します。このテストでは、大規模な実行の途中で小規模な実行を行う方が適切な表現である可能性があることに注意してください。
したがって、オプション1の場合、ブロックの割り当てはfallocate
を介して事前に割り当てられており、メタデータは書き込みの前に設定されているため、ブロックの割り当てはすでに(そして迅速に)行われているため、すべてのdata=ordered
セマンティクスを回避できる場合があります。 。これが実際に当てはまるかどうかをテストすると便利です。パフォーマンスは向上しますが、ある程度の自信はあります。
オプション2では、イオニスをもう少し使用できます。 CFQはプロセスごとにIOを整理しようとしますが、各プロセスを通じてIOのシェアが向上することがわかるように、期限はCFQよりも明らかに速いです。
私はどこかで(今すぐソースを見つけることができません)、dirty_background_ratioが個々のコミットプロセスに対する書き込みをブロックし(事実上大きなプロセスを遅くし)、1つのプロセスが他のすべてを飢えさせるのを防ぎます。その振る舞いについて今私が見つけることができる情報がどれほど少ないかを考えると、これがうまくいくとは確信が持てません。
ああ:fallocate
はエクステントに依存しているので、ext4を使用する必要があることを指摘しておく必要があります。
私は自分の質問に答えていますが、誰かがもっと良いものを提案できれば、私は非常に感謝します:)
テストの最後に4GBのダーティメモリがあるので、上記のテストではIOスケジューラが呼び出されていないと結論付けました。そうですか?
これは完全に間違っています。ダーティメモリの量は良い指標ではありません。これは、iostatを実行し、dd oflag = syncの実行中に大量の書き込みが行われていることを確認するだけで簡単に証明できます。
何がブロックされているかをより深く調査する方法はありますか?注目すべき興味深いカウンターはありますか?
perf record -e 'jbd:*' -e 'block:*' -ag
新しいカーネルの場合は、jbdをjbd2に置き換えます。
競合の原因について何か考えはありますか?
実際、data = orderedのext3の場合、ジャーナリングスレッドはディスク上のデータをフラッシュする役割を果たします。フラッシュは書き込み順に発生します。フラッシュの頻度は、ファイルシステムをマウントするときにcommitオプションを使用して制御できます。
興味深い実験:commit = 60でファイルシステムをマウントし、ライトバックスレッドを無効にします。最初のddを実行すると、2秒で完了し、iostatはIOが生成されなかったことを示します!
Oflag = syncを指定して2番目のddを実行すると、最初のddによって生成されたすべてのIOがディスクにフラッシュされます。
同期モードで最初のddを実行するか、dirty_ratio値を減らすことを考えています。
記録として、両方のソリューションで良い結果が得られます。もう1つの良いアイデアは、これらの大きなファイルを別のファイルシステムに配置することです(おそらくdata = writebackでマウントされます)
これは、SLES11以前のカーネルに特にリンクされていません。私が試したすべてのカーネルで同じ動作が発生します。
これはext3の予想される動作です。このファイルシステムでは、同期書き込みブロックは、l all前のダーティブロックがディスクに書き込まれるまで続きます。これが、開発者が過去数年間に同期された書き込みを完全にスキップした正確な理由です。
Ext4、XFS、ZFS、およびBTRFSはすべて、この点ではるかに優れています。 ext4が多かれ少なかれext3のドロップイン代替品であることを考えると、実際にファイルシステムをアップグレードする必要があります。