Linux の free コマンドで free が少ないとき:buff/cache と available の読み方
free コマンドの free 欄が小さくても、メモリ不足とは限りません。buff/cache、available、used の意味を /proc/meminfo とカーネルのソースから確認し、キャッシュを習慣的に破棄すると性能に影響しうる理由を説明します。
サーバーで free -h を実行すると、free 欄がごく小さく、buff/cache 欄が大きいことがよくあります。この数字だけでメモリ不足とは判断できません。新しいプログラムに渡せるメモリ量のカーネルによる見積もりは、別の available 欄に表示されています。
各欄の値は /proc/meminfo から来ている
free は procps-ng に含まれるコマンドです。メモリを独自に集計するのではなく、カーネルが出力する /proc/meminfo を読んで表示しています。procps-ng 4.x の free(1) マニュアルに書かれた対応は次のとおりです。
| free の欄 | /proc/meminfo の項目 | 意味 |
|---|---|---|
total |
MemTotal | 使える RAM の総量 |
free |
MemFree | 何にも使われていないメモリ |
shared |
Shmem | 主に tmpfs と共有メモリ |
buff/cache |
Buffers + Cached + SReclaimable | カーネルのバッファ、ページキャッシュ、回収可能な slab |
available |
MemAvailable | スワップせずに新しいプログラムへ渡せる量の見積もり |
used |
total − available | 使用中、または渡せないメモリ |
free -w を使うと buffers と cache が別々の欄になります。表にある元の値をすべて見るには、次のコマンドを使います。
grep -E '^(MemTotal|MemFree|MemAvailable|Buffers|Cached|SReclaimable|Shmem):' /proc/meminfo
free が小さいのはよくあること
Cached の大部分は、ディスクから読んだファイルのデータをメモリに保持するページキャッシュです。同じデータをもう一度読むとき、ストレージからの再読み込みを避けられます。Linux は RAM をこうしたファイルのページキャッシュに使うことができ、メモリが足りなくなればその多くを回収できます。そのため、ファイルを多く読むサーバーで MemFree が小さいのはよくあることで、それだけでは問題の兆候とは言えません。逆に、MemFree が小さいことがシステムの健全さを示すわけでもありません。
free と cache を足してはいけない理由
以前は free と cached を足して空きメモリとみなす方法が一般的でした。MemAvailable を追加した 2014 年のカーネルのコミット(Rik van Riel)は、この計算は今ではほぼ必ず不正確だと説明しています。Cached には共有メモリや tmpfs、ramfs のように、キャッシュを捨てても回収できないメモリが含まれ、回収可能な slab は含まれていないからです。正確に見積もるにはカーネル内部の知識が必要なため、カーネル自身が計算して出力することになりました。この項目は Linux 3.14 から存在します。
available の見積もり方
Linux v7.2 のソースにある si_mem_available() は、おおよそ次の順で計算します。
- 空きページ数から、カーネルが予約しているページを引く。
- ファイルのページキャッシュ(active と inactive の file LRU)を足す。ただし、その半分と全 zone の low watermark の合計のうち小さいほうは残しておくべきだと仮定して差し引く。
- 回収可能な slab と、その他の回収可能なカーネルメモリを足し、2 と同じ方法で一部を差し引く。
- 結果が負なら 0 とする。
この計算はヒューリスティックで、カーネルのバージョンによって変わる可能性があります。結果は見積もりで、保証された値ではありません。
used の値は procps のバージョンによって違う
procps-ng 3.3.16 は used を total − free − buffers − (Cached + SReclaimable) で計算し、これが負になる場合は total − free を使っていました。procps-ng 4.0.1 からは total − available に変わっています。そのため、同じメモリ状態でも procps のバージョンによって used の数字が異なることがあります。複数のシステムの used を比べる前に、free -V でバージョンを確認してください。
drop_caches は解決策ではない
/proc/sys/vm/drop_caches に 3 を書き込むと、クリーンなページキャッシュと、dentry や inode などの回収可能な slab オブジェクトが破棄されます。その結果、free 欄が大きくなることがあります。しかしカーネルのドキュメントは、このファイルはキャッシュの増加を制御する手段ではないと説明しています。カーネルは、メモリが必要になればこれらのオブジェクトを自ら回収します。破棄したデータやオブジェクトが再び必要になると、読み込みや再構築が必要になり、I/O と CPU の負荷が増えることがあります。そのためドキュメントは、テストやデバッグの環境以外での使用を勧めていません。まだディスクに書き込まれていないダーティなオブジェクトは、この方法では解放されません。
まとめ
メモリの余裕を最初に確認する指標としては、free より available が適しています。ただし、単一の値や減少傾向だけでメモリ不足とは判断できません。
OS の数字が思ったとおりにならない別の例として、ファイルを削除してもディスク容量が空かない理由も参考になります。