Skip to content

Instantly share code, notes, and snippets.

@kazuho
Last active November 8, 2024 03:32
Show Gist options
  • Save kazuho/074e2c82a2c09b9255c5 to your computer and use it in GitHub Desktop.
Save kazuho/074e2c82a2c09b9255c5 to your computer and use it in GitHub Desktop.
Linuxカーネルのreadahead、うまく動いてないケースがあるのかも

大きなテキストファイルをawkで処理するときにcatで投げ込むと速い理由のような事象が発生する原因についての推察。

自信はあまりない!

Linuxカーネルのreadahead実装についての理解

  • __do_page_cache_readaheadは、次にreadaheadを実行すべきページについてのみReadaheadフラグをたてる
  • 次にreadaheadを実行すべきページ「以降の全てのページ」ではない
  • do_generic_file_readはReadaheadフラグの立っているページをreadするタイミングでpage_cache_async_readaheadを呼ぶ
  • page_cache_async_readaheadはBDI_sync_congestedが立っている場合はreadaheadしない
  • Linuxは書き込みを遅延しているが、一定の条件下において、BDI_sync_congestedフラグをセットして書き込みを行うことがある?(要確認)
  • dirty pageの比率が高くなったり一定時間がたったら強制フラッシュをしてるはずだけど、その際の内部ステートがどうなってるか、という話

参考: readahead.c - On-demand readahead design.

当該ベンチマーク

  • awkのread(2)サイズは4KB(つまりページサイズと同一)
  • 当該ベンチマークは、読み込みと同時にawkの出力をファイル書き込んでいる
  • 書き込み量は不明だが、ベンチマークに50秒以上かかっていることを考えると、ベンチマーク実行中にディスクに対するwrite i/oが発生していると推測できる
  • この書き込みがBDI_sync_congestedフラグをセットしているとすると、同フラグがセットされた状態でread(2)がReadAheadフラグのたっているページを読んだ場合、非同期のreadaheadは実行されない
  • 非同期のreadaheadが実行されないままフラグの立っていたページを通過した場合、page missが発生するまでreadaheadは行われない
  • 以上がawk file > outという使い方において、i/o waitが発生する原因と考えられる

他の結果との整合性

  • dd if=file bs=4k | awk > out のように、(2MBもあるReadAheadバッファと比べて)少量のバッファを用いるだけでi/o waitが消え去るのは、上述のように非同期のReadAheadに失敗していた場合において、catのread(2)がブロックする間も、パイプのバッファに入っているデータの処理をawkが続けることが可能だからである。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment