💻

ディスクキャッシュをさせないで連続で読み込みをしたい

2024/12/25に公開

はじめに

以下のようなことを実現するためにやったことを書き残します。
・ファイルアクセス(読み込み)を連続で実施し続けたい。
・ファイルアクセスにおいては、ディスクキャッシュに乗らない状態にしたい。
・結果はエラー時のみ画面とファイルに出力したい。
・ファイルアクセスを実施した時刻を画面とファイルに出力したい。
・ワンライナーで表現したい。
なお、RHEL8(カーネルバージョン4.18あたり)で確認してます。

結果

以下コマンドで要望を満たすことが実現できました。

while true; do echo 3 > /proc/sys/vm/drop_caches; cat "読み込むファイルを指定" 2>&1 1>/dev/null| tee -a "出力ファイルを指定"; date| tee -a "出力ファイルを指定"; sleep 1; done

以降は上記コマンドの内容の補足をしていきます。

ファイルアクセスを連続で実施し続けたい部分

whileでループさせてますが、while trueとしているため、常に真となり、無限ループしてくれます。なお、sleepとか入れないとすごいスピードでループします。今回は1秒間隔の情報があれば良かったため、sleep 1としてます。処理を止めるときはCtrl+Cを実施します。

while true; do "繰り返し実行したいことをここに指定"; sleep 1; done

ファイルアクセスにおいては、ディスクキャッシュに乗らない状態にしたい部分

かなりざっくりですが、ファイルアクセスするとカーネルはキャッシュして、2回目のアクセスはメモリから読み込みます。通常の利用シーンにおいては考慮不要な部分かと思いますが、今回はキャッシュから読み込まないようにする必要があったため、キャッシュをクリアしています。
キャッシュクリアはdrop_cachesに値を書き込むことで実現しています。[1]
drop_cachesに1(ページキャッシュをクリア)、2(dentryキャッシュ、inodeキャッシュをクリア)、3(1と2の両方)を指定した場合とキャッシュクリアなしの場合の読み込み負荷状況は以下のような感じでした。

ページキャッシュだけでなく、dentryキャッシュ、inodeキャッシュまでクリアする方(すなわち3)が、今回やりたいことには近づきそうな感じでした。
なお、while内にecho 3 > /proc/sys/vm/drop_cachesを記載しているので、ループする度にキャッシュクリアをしています。

結果はエラー時のみ画面とファイルに出力したい部分

コマンドの以下部分です。

cat "読み込むファイルを指定" 2>&1 1>/dev/null| tee -a "出力ファイルを指定"

前提として、ファイルディスクリプタの番号1は標準出力、番号2は標準エラー出力です。
まず、1>/dev/nullで1を/dev/nullにリダイレクトしてます。これによって標準出力を捨ててます。
次に、2>&1です。>&は左に書かれたファイルディスクリプタの出力先を、右に書かれたファイルディスクプリタの出力先に変更するという意味です。なので、2>&1で、標準エラー出力の出力先を標準出力に変えてます。
最後に「cat "読み込むファイルを指定" 2>&1 1>/dev/null」の出力結果をパイプでteeコマンドに渡してます。teeコマンドは標準入力に対し、標準出力とファイル出力をします。teeコマンドに標準入力として渡すために、2>&1で出力先を変えている感じです。なお、-aオプションでファイルに追記をするようにしてます。

ファイルアクセスを実施した時刻を画面とファイルに出力したい部分

ここはシンプルにdateコマンドの出力結果をパイプでteeコマンドに渡して、標準出力とファイル出力させてます。

date| tee -a "出力ファイルを指定"

おわりに

シンプルではあるのですが、結構試行錯誤してしまいました。またディスクキャッシュに乗せない部分はdentryとかinodeとかを調べていくと時間が溶けていきますね。。

脚注
  1. https://access.redhat.com/ja/solutions/701133 ↩︎

Discussion