TL; DR
- Linuxのvm.swappinessは、「メモリの空き容量を増やす際にfile cacheの解放とanonymous pageのスワップのどちらを優先するか」を調整するカーネルパラメータです
- ハードウェアの進歩に伴い、従来の0から100までではなく0から200までの値を指定できるようになっています
- コンテナ環境ではcgroup v1では設定が可能ですが、cgroup v2では直接設定できないようです
背景
Linuxのvm.swappinessというカーネルパラメータを用いてスワップの発生確率を調整できると聞き、具体的にどういうことかを調べてみました。
swappinessとは?
Systems Performance 7.3.2のこの図(書籍より引用)がわかりやすく、仮想メモリ管理で空きメモリを確保する際に、ページキャッシュを解放するのかそうではない領域(anonymous page)をスワップするのかを選ぶ重みづけを行うカーネルパラメータというのが一言で言うとの説明になります。
具体的な意味としては、
- 0から200の整数で指定
- 小さいほどpage cache(file cache)の解放を優先
- 大きいほどanonymous pageのスワップを優先
- 100で優先度が同じ
- デフォルトは60 というものとなります。
つまり、0にするとスワップは全く行われないということになります。1
諸々参考になる情報ソース
/proc/sys/vm/swappiness_
The value in this file controls how aggressively the kernel
will swap memory pages. Higher values increase
aggressiveness, lower values decrease aggressiveness. The
default value is 60.
cf. /proc/sys/vmのman
The swappiness value, ranging from 0 to 200, controls the degree to which the system favors reclaiming memory from the anonymous memory pool, or the page cache memory pool.
cf. RHEL10のドキュメント
This control is used to define the rough relative IO cost of swapping and filesystem paging, as a value between 0 and 200. At 100, the VM assumes equal IO cost and will thus apply memory pressure to the page cache and swap-backed pages equally; lower values signify more expensive swap IO, higher values indicates cheaper.
cf. Linuxカーネルドキュメント
Q. **swappiness**って本当に「スワップしにくさ」を設定できるの?
A. はい、本当です。
ただそれが本当にあなたの望む動作なのかについては注意が必要です。
**swappiness**は、**0から100**までの値を設定することができ、それはメモリを回収(scan)するときにどこから回収するかに効いて、200分率で下記のように使われる
- **(swappiness)の割合でANONYMOUSE**をscanする
- **(200-swappiness)の割合でfile_backed**をscanする
cf. Linuxのswappinessは本当にスワップしにくさを設定できるのか #kernel - Qiita
最新のカーネルにおけるアップデート
ここまでの説明で、vm.swappinessは0から100までじゃないの?と思われた方もいるかもしれません。 確かに昔の記事やドキュメントではそのように書かれています。
これはどちらかが嘘をついているというわけではなく、カーネルv5.8-rc1から従来までの0から100ではなく0から200までの設定へと変更されたためです。 これは、SSDなどのランダムIOに強いストレージやRAMに圧縮したスワップを置くzram・zswapが登場したことによって以前よりもスワップのコストが下がり、file-backedなpageの解放よりもスワップを優先したいというニーズが出てきたためとされています。
なお、この変更はあくまでも指定可能な範囲が増えたというだけであり、パラメータの意味やデフォルト値は変わらないようです。
cf. 変更が行われたコミット
コンテナにおけるswappiness
現在はLinuxマシンをそのまま使うということは少なく、コンテナ技術を用いることが多いですが、その基盤となっているLinuxのcgroupsにおいてswappinessはどのようにサポートされているのかを調査してみました。
cgroup v1での状況
memory.swappinessというパラメータでcgroup毎のvm.swappinessを設定できるようです。
cf. Linuxカーネルドキュメント
また、dockerでは—memory-swappinessという専用のコマンドラインオプションがあるため、直接的にはこれを指定するのが良いでしょう。
cf. Docker公式ドキュメント
余談ですが、—memoryと—memory-swapのパラメータを同じにすることでコンテナのswapを無効にできると書いてあり、「スワップを無効にしたい」というだけであればこちらがより簡単です。 ただし明示的なメモリlimitを設定することになるので、あまり低めに設定するとOOMのリスクが高まることに注意が必要です。
cf. Docker公式ドキュメント
cgroup v2での状況
Per memcg knob does not exist in cgroup v2.
とあるように、cgroup v2ではcgroup毎のswappinessは指定できないようです。 cf. Linuxカーネルドキュメント
意図としては、この設定はワークロードそのものよりもハードウェアに関係する話であり、指定したい場面というのは実質的にスワップを無効にしたいというもので、それはmemory.swap.maxという他のパラメータで実現できるというのが説明されています。
cf. cgroups v2におけるswappinessについて解説されたstackoverflow cf. cgroups v2に関する議論のissue