[linux]Linuxでキャッシュをクリアする

2016年10月17日月曜日

linux

grepのようにファイルを読み込む処理の実行速度を計測するときに1つ気をつけなくちゃいけないことがある。
同じファイルに対する操作を2回、3回と続けるとファイルの内容がメモリにキャッシュされて1回目と比べて、処理が速くなることがあるからだ。

これはどちらの処理結果が正しいということではなく、処理の種類によってどちらの結果を採用するかを決めたほうがいい。

grepのようなコマンドの処理であれば、キャッシュされていることを前提とせずに毎回HDDから読むと考えたほうがいいだろう。
逆にDBMSやWebサーバが参照しているファイルはキャッシュに乗っていることを前提として考えたほうがいいかもしれない。

実際にgrepを同じファイルに対して複数回実行してみよう。

$ yes 1234567890 | head -n 10000000 >test.dat
$ echo 0987654321 >>test.dat

$ time grep 0987654321 test.dat
0987654321

real    0m11.479s
user    0m0.001s
sys     0m4.071s
$ time grep 0987654321 test.dat
0987654321

real    0m0.813s
user    0m0.684s
sys     0m0.126s
$ time grep 0987654321 test.dat
0987654321

real    0m0.813s
user    0m0.690s
sys     0m0.120s
$

2回目以降の処理速度が格段に速くなっているのがわかる。

次に毎回、ページキャッシュをクリアして計測してみよう。

キャッシュをクリアするためには/proc/sys/vm/drop_cachesに値を書き込む。

https://linuxjm.osdn.jp/html/LDP_man-pages/man5/proc.5.html
/proc/sys/vm/drop_caches

sudoもしくはsuでrootにスイッチして、1(ページキャッシュ),2(dentryとinode),3(ページキャッシュとdentryとinode)のいずれかを書き込む。
ファイルの内容がキャッシュされるのは1のページキャッシュなので、これをクリアするために1を書き込む。

$ sudo sh -c 'echo 1 >/proc/sys/vm/drop_caches'
# もしくはrootで
# echo 1 >/proc/sys/vm/drop_caches
# time grep 0987654321 test.dat
0987654321

real    0m9.509s
user    0m0.024s
sys     0m1.802s
# echo 1 >/proc/sys/vm/drop_caches
# time grep 0987654321 test.dat
0987654321

real    0m10.276s
user    0m0.033s
sys     0m1.585s
# echo 1 >/proc/sys/vm/drop_caches
# time grep 0987654321 test.dat
0987654321

real    0m9.739s
user    0m0.033s
sys     0m1.570s
#

今回は3回ともに10秒前後かかっていることがわかる。

ちなみに2に登場するdentryとinodeについては以下を参照してほしい。

https://linuxjf.osdn.jp/JFdocs/The-Linux-Kernel-10.html
EXT2の説明なので、情報は古いかもしれないけど、考え方は同じだと思う。