$ free -h
total used free shared buffers cached |
Linuxのメモリ使用についてよくわかっていなかったので調べてみた。
Linuxのページキャッシュについて
まずキャッシュとは、データへのアクセスを速くするために、より高速な記憶装置に一時的に保存する仕組み。
で、ページキャッシュとは、
- CPUはストレージから直接読むことはできない
- そのため、ストレージのデータを一旦メモリにロードしてから読み込む
- Linuxは一度ストレージから読みだしたデータは可能な限りメモリにキャッシュし、次回以降の読み込みが高速に行われる
- Linuxは、メモリ領域をページという単位(ページの大きさははCPUの種類で異なる)で管理する
- メモリ上に読みだしたデータのキャッシュのことを「ページキャッシュ」と呼ぶ
(補足)
freeコマンドで見ると、cached で示されるページキャッシュと buffers で示されるバッファキャッシュが存在する。 ページキャッシュはファイルシステムに対するキャッシュであり、ファイル単位でアクセスするときに使用されるキャッシュ。 もうひとつのバッファキャッシュは、ブロックデバイスを直接アクセスするときに使用されるキャッシュになる。
ページキャッシュの簡単な流れとしては、
- データにアクセスする処理が発生
- それはページキャッシュ上に無い
(キャッシュ上にデータがあれば、ストレージにアクセスせずキャッシュのデータを使う) - メモリに空き領域がある
(メモリ上に空きが無ければ、ストレージから読み出したデータをキャッシュするため、古いキャッシュを捨て、新しいキャッシュを構築する) - ストレージから読み出し、新しいキャッシュを構築する
つまり、データにアクセスするということは、ページキャッシュを構築することになる。
Linuxは空いているメモリをページキャッシュに使おうとするので、時間とともにページキャッシュは増加していく。そして、ページキャッシュは新たなストレージへのアクセスがあっても、メモリが必要にならない限り解放しない。
利用可能なメモリ量
おおよその利用可能なメモリの量は、freeコマンドで表示される1行目(Mem: )のfreeの値ではなく、2行目(-/+ buffers/cache:)のfreeの値を確認する。
2行目のfreeは、1行目のfreeにbuffersとcachedを加えた値。
これは、上述の通り、バッファ(buffers)とキャッシュ(cached)が使用している値も結果的には空きメモリとして使用できるため。
1行目のfreeだけ見て、少ないと思うようなことがあっても、2行目を確認してみると問題ないことが多い。
ページキャッシュは必要が無ければメモリ解放しないが、一方で、ページキャッシュは使って無ければ、すぐに破棄することは可能。つまり破棄できない領域と破棄できる領域がある。
freeコマンドの2行目のfreeには、この破棄できない領域のキャッシュも含まれている。
破棄可能なキャッシュを確認してみる。vmstatコマンドを使う。
$ vmstat -a
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- |
"-a" オプションで、メモリキャッシュの アクティブ "active" (利用中のため開放できない領域)と、非アクティブ "inact" (最後に利用されてから一定時間が経過しているので廃棄できる領域)の内訳を確認できる。
利用可能なメモリ量を算出するなら、freeコマンドで確認したMem行のfreeと、vmstat -aコマンドで確認したinactが実際に利用可能なメモリ量になる。
メモリキャッシュのクリア
これまでの内容で、キャッシュは空きメモリの一部と見れるので、これらが増加したからといってメモリを圧迫している訳ではないので、無理やり解放させる必要は無い。キャッシュはアクセス高速化のためなので、むしろ有益です。
ただ、パフォーマンス測定の場合は素の状態で正しく計測したいので、クリアしたほうが良い。
キャッシュの解放をコマンドからできる(Linuxカーネル 2.6.16以降)。
$ echo 3 > sudo /proc/sys/vm/drop_caches
または$ sudo sysctl -w vm.drop_caches=3
数字は解放したいメモリを示す。
1: ページキャッシュ解放
2: dentry、inode 解放
3: ページキャッシュ、dentry、inode 解放
ページキャッシュがまだストレージへ同期されていない分を Dirty cache という。
この操作では、Dirty cahce は解放の対象外となる。
解放する前に、syncコマンド使って、Dirty cache を書き出してから、
解放を行うことで、より効果的な開放が行える。
$ sync
$ echo 3 > sudo /proc/sys/vm/drop_caches