dd 書き込み速度と VFS ページ キャッシュについて混乱しています

dd 書き込み速度と VFS ページ キャッシュについて混乱しています

Linux VFS ページ キャッシュと調整可能なパラメータに関するいくつかの記事を読んだ後、dirty_ratioページ キャッシュは読み取りと書き込みの両方のキャッシュ レイヤーとして機能するという印象を受けました。

しかし、以下の簡単なテストを使用すると、ページ キャッシュにあるファイルの読み取り速度は向上しますが、書き込みには効果がないようです。

例えば

キャッシュをクリアしてファイルに書き込みます。

# swapoff -a
# echo 3 > /proc/sys/vm/drop_caches

# dd if=/dev/zero of=/home/flo/test bs=1M count=30
30+0 records in
30+0 records out
31457280 bytes (31 MB) copied, 0.182474 s, 172 MB/s

ファイルが実際にページキャッシュにあるか確認する

# vmtouch /home/flo/test 
           Files: 1
     Directories: 0
  Resident Pages: 7680/7680  30M/30M  100%
         Elapsed: 0.000673 seconds

ファイルから読み取り、実際にキャッシュからのものであることを確認します。

# dd if=/home/flo/test of=/dev/null bs=1M count=30
30+0 records in
30+0 records out
31457280 bytes (31 MB) copied, 0.00824169 s, 3.8 GB/s

速度の違いを証明するために、キャッシュを削除して再度読み取ります。

# echo 3 > /proc/sys/vm/drop_caches
# dd if=/home/flo/test of=/dev/null bs=1M count=30
30+0 records in
30+0 records out
31457280 bytes (31 MB) copied, 0.132531 s, 237 MB/s

私は dd で DIRECT_IO を使用していないので、ページ キャッシュがライトバック タイプのキャッシュとして使用されることを期待していました。そして、dirty_ratioまたはに基づいてdirty_expire_centiseconds、最終的にデータがディスクにコミットされます。

VFS が読み取りプロセスと書き込みプロセスを特に書き込み時にどのように異なる方法で処理するか、またなぜ速度が向上しないのかを説明していただけますか。

たとえば RAID コントローラーにあるようなライトバック キャッシュのように動作するように、書き込みキャッシュで VFS をより積極的にする方法はありますか。

ありがとう

fLo

答え1

man ext4 には (no)auto_da_allocオプションに関する次のような紹介があります:

多くの壊れたアプリケーションは fsync() を使用していません...

どうやらこの件には長い経緯(データ損失に関する悲劇)があるようだ。それは遅延割り当てファイルシステムブロックの。ext2/3 にはなかった機能ですが、ext4 だけでなく、非常に重要な機能です。

アプリケーションが同期せず、ユーザーも手動で同期せず、カーネルも 30 秒後にしか同期しない場合は、ファイルの書き換えが必要なときにファイルシステムがすぐに同期を実行する方がよいでしょう。そうしないと、DA では、停電時に簡単に悪いことが起こります。最後の変更が失われるよりも悪いことです。

dd コマンドがなければ、conv=notruncate上書き時に「アプリケーション」のように動作します。新しいファイルを作成するには既存のファイルを削除する必要があります。そうしないと、既存のファイルの方が長い場合に混在したファイルが作成されます。

ext4 ではこの動作をオフにすることができます。これでmount -o remount,noauto_da_alloc ...、切り捨て後も長時間ブロック書き込みを実行できるようになります。

次の攻撃性のレベル定期的な書き戻しの有効期限を 30 秒に、チェック間隔を 5 秒に (/proc/sys/vm/ の dirty_..._centisecs 値) 上げることです。デフォルトの 30/5 では、より速く削除しない限り、一部の新しいファイルは 30 秒後に書き込まれます。

VFS が未使用ページに対して積極的であればあるほど、ファイルシステムはブロックデバイスに対して積極的である必要は少なくなります。


マウントオプションとライトバックパラメータ

]# findmnt --real
TARGET       SOURCE     FSTYPE OPTIONS
/            /dev/sda3  ext4   rw,relatime,noauto_da_alloc
|-/root/sda1 /dev/sda1  ext2   rw,relatime
`-/root/16   /dev/sda16 ext4   rw,relatime

このような設定では、上書きは sda16 ではすぐに同期されますが、他の 2 つでは同期されません。

現時点では、定期的な書き戻しを完全にオフにしました(したと思います)。

]# grep '' /proc/sys/vm/*centisecs
/proc/sys/vm/dirty_expire_centisecs:720000
/proc/sys/vm/dirty_writeback_centisecs:0

そして今、私はついに汚いページを集めています:

]# grep nr_dirty /proc/vmstat 
nr_dirty 10077
nr_dirty_threshold 437320
nr_dirty_background_threshold 174671

試すこれらを収集して、デフォルトの 10% バックグラウンド比率に何とか近づけます。昨日、サスペンド ツー RAM スリープに移行したときに同期されました。当然です。何 MB ものダーティ ページを抱えてスリープしたい人がいるでしょうか?

mm/writeback.c詳細は大変複雑で、コメントからもそれがわかります。1 つの問題は、「1000 dd が同時にダーティ状態になり始める」というスロットリング ポイントを見逃さないことです。「ライトバック」は、長期的には、この約 10% の bg-ratio を目標としているようです。上記の例が示すように、この 10% (合計/使用可能な RAM の) は、通常の (最小限の) 使用ではいっぱいになるまでに時間がかかります。1 分間のブラウジングで、およそ 1000 ページがダーティ状態になります。


理論の後は具体的な証明

上記のファイルシステムのうち 2 つで 10 ブロックをテストしました。

]# dd if=/dev/zero of=test10  bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.0076396 s, 1.4 GB/s

]# dd if=/dev/zero of=test10  bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00514406 s, 2.0 GB/s

-> ルート パーティション (上記 sda3) に noauto_da_alloc を使用すると、上書きがさらに高速になります。

デフォルトでマウントされた ext4 (上記の sda16) では速度が低下します。

]# rm test10 

]# dd if=/dev/zero of=test10  bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00800839 s, 1.3 GB/s

]# dd if=/dev/zero of=test10  bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.0740824 s, 142 MB/s

...次のように、上書き全体が同期されるためですvmstat 1 |cut...

    0     0
    0     0
    0     0
-----io----
   bi    bo
    0 10240
    0     0
    0     0

sync遅延割り当てによる手動

良い点は、必要なときに実行でき、個々のファイルだけでなくドライブ全体に対しても実行できることです。

また、アンマウント、シャットダウン(およびサスペンド)も含まれます。

悪い点は、(上書き)書き込みと同期の間にクラッシュ/電源障害が発生した場合に、長さゼロの「破損」のリスクが発生することです。つまり、実際に安全であるのは、外部ストレージに置いたもの、または 2 つだけということです。


結論が見つかりません。簡単な解決策はなく、長い(ただし少なくとも論理的な)説明しかありません。

答え2

高速な動作を確認するには、まずこれを行う必要がありますrm test。たとえば、dd150MB/秒ではなく 1GB/秒というレポートが表示されます。

参考文献:

参照資料では、なぜこれを試そうと思ったのかのみが説明されていますが、実際に IO がブロックされる理由については説明されていません。

私のコンピュータでは、ブロックは2016年に追加された新しいWBT(「ライトバックスロットリング」)コード内でのみ発生するようでした。あなたが質問した。私は分析していないなぜこれが原因です。WBT を無効にすると、この問題は解消されました。

私のカーネルバージョンは です4.18.16-200.fc28.x86_64

strace -Tは、すべての時間がclose()に費やされたことを示しています。これが私にとって最も理にかなっています。私も試してみましたperf。期待通りには動作しませんでしたが、次のようなスタックトレースが表示されました。

dd 17068 [003] 475165.381526:       sched:sched_switch: dd:17068 [120] T ==> kworker/3:1H:19326 [100]
    ffffffffa390c172 __sched_text_start+0x352 ([kernel.kallsyms])
    ffffffffa390c172 __sched_text_start+0x352 ([kernel.kallsyms])
    ffffffffa390c6a8 schedule+0x28 ([kernel.kallsyms])
    ffffffffa30def32 io_schedule+0x12 ([kernel.kallsyms])
    ffffffffa3461ed7 wbt_wait+0x337 ([kernel.kallsyms])
    ffffffffa342ee33 blk_queue_bio+0x123 ([kernel.kallsyms])
    ffffffffa342d114 generic_make_request+0x1a4 ([kernel.kallsyms])
    ffffffffa342d3c5 submit_bio+0x45 ([kernel.kallsyms])
    ffffffffa3377d78 ext4_io_submit+0x48 ([kernel.kallsyms])
    ffffffffa335da2c ext4_writepages+0x70c ([kernel.kallsyms])
    ffffffffa3209311 do_writepages+0x41 ([kernel.kallsyms])
    ffffffffa31f808e __filemap_fdatawrite_range+0xbe ([kernel.kallsyms])
    ffffffffa334b9ec ext4_release_file+0x6c ([kernel.kallsyms])
    ffffffffa32a9d4e __fput+0xae ([kernel.kallsyms])
    ffffffffa30cf474 task_work_run+0x84 ([kernel.kallsyms])
    ffffffffa3003e6e exit_to_usermode_loop+0xce ([kernel.kallsyms])
    ffffffffa300425d do_syscall_64+0x14d ([kernel.kallsyms])
    ffffffffa3a00088 entry_SYSCALL_64_after_hwframe+0x44 ([kernel.kallsyms])
        7fcca3a60654 __close+0x14 (/usr/lib64/libc-2.27.so)

それで、私は現在、WBT (「ライトバック スロットリング」) を有効にして I/O スケジューラをテストしていることを思い出しましたdeadline。WBT を無効にすると (互換性のない CFQ に切り替えることを含む)、再び高速な動作が得られました。

perfこれを確認するのに使用したコマンドは次のとおりです。

sudo perf record -e sched:sched_stat_sleep -e sched:sched_switch -e sched:sched_process_exit -gP -o ~/perf.data dd if=/dev/zero of=test bs=1M count=30
sudo perf script -i ~/perf.data | cat

答え3

を使用しないでくださいdd。たとえば、 を使用するcpと、書き込み用のページキャッシュが正常に取得されます。

関連情報