Chienomi

LinuxのSwapの解説の(私なりの)解説

Live With Linux::practical

Chris Downさんが執筆された “In defence of swap: common misconceptions” をHiroaki Nakamuraさんが翻訳された 「スワップの弁護:よくある誤解を解く」が公開された。

秀逸な記事であり、非常にわかりやすい。 ぜひご一読いただきたいのだが、いささか難しい部分と、疑問に思う部分があるように思われた。

そこで、私がもう少し一般ユーザーに近いレベルで、この記事を解説したいと思う。

もちろん、まずは当該記事を読むべきであり、当該記事で十分なのであれば私の記事を読む必要はないだろう。

また、この記事は本来一般的な構成とは逆になっている。 これは、解説部分で言及する内容が質問や検証にあるためであり、解説部分は後方にある。

質問

私は、「もしメモリが有り余る状況でもスワップは必要である、という話なのだろうか?」という疑問を持った。 そこで、Chris Downさんに質問してみた。 さらに、私のダメダメな英語を見かねたNakamuraさんが質問を直してくれた。

おふたりに深く感謝したい。

以下が回答である。

Swapping happens as part of reclaim, so we must have had at least some memory pressure beforehand to initiate the reclaim. We don’t proactively evict from swap as if the pages are hot, they’ll be faulted in anyway, and if they are cold, then there’s no reason to fault them in :-)

That is, it’s entirely possible we have swap pages used now even though there’s not currently memory pressure just because we don’t proactively fault them back in to memory, if I understand your question.

In general the first thing I’d evaluate is your understanding of “needed” caches/buffers/anonymous memory. This is pretty much impossible to reason about or calculate in the general case unless you use some combination of pressure metrics (to know the limit) and…

…something like Senpai (https://github.com/facebookincubator/senpai) to compress the workload and monitor pressure values. Sorry that I am not able to reply in Japanese, and I hope I understood!

ふむふむ。 私が重要だと理解したのは以下のポイントだ。

第一に、「swapから呼び戻すのはメモリ回収において行われる」ということだ。 頻繁にアクセスされるswap領域はいずれメモリ内に呼び戻される。一方、そうでない(coldな)ものはそうではない。 まぁ、これは普通の理解だろう。

第二に、「swapが使われるメモリ圧」がかかっているかどうかというのは、計測はそんなに簡単ではないということだ。 (でもなんでSenpai??)

この二点は容易に受け入れられる。 そして同時に、「メモリ圧が全くかからない」状態であればいずれにせよswapは使われない、つまり物理メモリが無限にあるならばswapは必要ない、という結論で良いようだ。 ただし、それは容易に計測できるものではないと。

だが、現実問題として、私の環境は今は16GB RAMなのだが、通常の利用においては5GBくらいしか使われない。

              total        used        free      shared  buff/cache   available
Mem:       16004856     3161344    10880068      455232     1963444    12067648
Swap:      17604068           0    17604068

ちなみに、これはブラウザをいくつも立ち上げ、メーラーを立ち上げ、端末とかNemoを立ち上げ、LeafpadとVSCodeを立ち上げて執筆している状態である。 こんな状態であるため、全くswapが使われない。 残念ながら私はatopによるロギングの経験がないが、Conkyによってスワップ量は常に監視しているが、最近は16GB以上のメモリがあるマシンでスワップが使われたのを見たことがない。 (8GBのThinkPadに関しては何度か見たことがある) これが、私は「十分なメモリがあればswapは使われないのでは?」という感覚の根拠である。

その意味ではChris氏と私では観点が異なる。 私のは素朴な「デスクトップ利用としての」話をしているが、Chris氏はそうではない。 また、私が原理的な話をしているのに対し、Chris氏は実践的な話をしている。 (いってしまえば、私のほうがだいぶ浅い話をしている)

また、Chris氏は「swapがあって悪いことはない」という観点から述べている点も違いとしてあるだろう。 私はswapが悪いとは全く思っていないので、実用的にはとりあえずswapを作っておけばよいことを知っているからだ。

個人的な経験

今でこそ16GBが「有り余るメモリ」だが、ほんの数年前までそんなことはなかった。 ログイン時のメモリ使用量が8GBを越える程度で、最終的には20GBを越える程度になっていたので、私は「今のLinuxに望ましいメモリは24GB以上」というような表現していた。

それがどうしてこんなに減ったのか。 もちろん、メモリを延々食い続けるMikutterやV2Cといったアプリを私が使わなくなったというのも大きいだろうが、これらを使わなくてもやはり16GBを越えるメモリが必要であった。 なお、これは私が使っているOrbitなど、メモリを大量に使うプログラムは除外した話である。

ディストリビューションの違いというのもあるかもしれないが、少なくともManjaro LinuxでCinnamonという意味と同じ構成になったときも依然としてこの状況であった。

それが今や、ログイン時だと800MBとかいうレベルで、普通に4GBメモリでも処理できるようになってしまっているのだから、一体何が変わったのだという感じではある。

また、swapに対する悪印象というのもちょっとわかる。

昔はメモリが少なかったので、必然的にswapは必要不可欠なものではあったのだが、昔のLinuxはかなり積極的にswapを使う仕様だった。それこそ、使用率が50%もいかないうちからである。 そして、割とhotなものをswapにおいてしまうので、パフォーマンス低下にも繋がっていた。 なにより、メモリ自体が小さいので激しいスラッシングが起きることが多く、swapが使われている状況は著しい性能低下のサインでもあった(これは別にswapに起因しているわけではない)。

解説

根本的な話

メモリというのは、「メモリに載っているからCPUが使える」というものではない。 CPUが扱うためにはCPUのメモリに載せる必要がある。いわゆる「メモリ」と呼ばれているものは、CPUからすれば外部のものなのだ。

だが、CPUのメモリは容量がとても小さいので、全てを載せておくことができない。 そのため、外からとってきて載せては捨てることになるのだが、小さな容量に載せられるものは当然ながら小さく、そのために頻繁にとってくることになる。 だからこそ速度の比較的速い「外部メモリ」が使われるのである。

これは、大皿と取皿の関係のようなものだ。

CPUキャッシュと外部メモリでは速度に相当な差があるが、それでも全体からみればメモリはかなり速い部類に入る。 そして速度を優先したデバイスであり、電源を失えば内容が損失される揮発性のものであり、容量も少ない、という特徴がある。

この貴重なメモリをより有効に活かすためにディスクを使うのがswapだ。 一般的に今のCPUはL3までキャッシュがあり、4段目に外部メモリがくる構造だが、ならばswapは5段目に位置することになる。 可能ならば使いたくないが、遅いもののより容量が大きいメモリを使うことで貴重なメモリを有効に活用するのが後段にあるものの役割だ。

swapは何をするか

記事において強調されていることは、私にとっては当たり前だが、そうでない人もいるかもしれない。 それは、 swapはあまり使わないがメモリから捨てることができないものを置いておく場所である ということだ。

つまり、 メモリが足りなくなったから追加のメモリとして使う場所ではない ということを意味している。

swapに置かれるのは何か? それは、メモリ上にあって、あまり使われないものである。

このあたりの話は昔小崎さん、もしくはまつもとさんが話しているのを聞いたことがある。 メモリが足りなければメモリを確保する必要がある。 方法は主にふたつ。メモリのとどめておく必要のないもの(例えば、既に全ての内容を書き出してあるキャッシュ、あるいはすでに終了したプロセスが確保したメモリ)を捨てるか、メモリにとどめておく必要のあるもの(例えば、現行プロセスが確保したメモリ)をswapに置くか、である。

swapがなければ、後者はできず、メモリは解放しなければならない。

これは、より容量が増加するというだけの意味ではない。 確かに、File-backedなメモリは全てではないが解放可能である1。ディスクに書き出してしまえば内容を失うことはないからだ。 だが、File-backedなメモリは非常に大きく性能に貢献している。必ずしも(プロセスのメモリである)AnonymousメモリがFile-backedメモリよりも優先してメモリにいるべきだ、ということにはならない。

SwapがなければAnonymousページをメモリから追い出すという方法はない。 そんなことをするとそのページを使っているプロセスが動かなくなってしまうからだ。 こうした、「捨ててしまうことができないページ」のディスク上の置き場がswap、というわけだ。

swapは必要か?

必要かどうかはともかくあったほうが良い。あって害にはならない。 これがChris氏の見解である。

以下は私見である。

パフォーマンス的な面でいえば確かにswapはあったほうがいい。 そもそも、メモリが足りなくなってswapを利用するためにパフォーマンスが低下する環境では、swapがなければシステムは死ぬ。

だが、swapがネックになるケースもある。それは、暗号化だ。

システムを暗号化するとき、swapも暗号化しなければならない対象である。 これがなかなかめんどくさい。 さらに、暗号化のコストは高いため、暗号化されたswapへの出入りで計算リソースをより大きく消費されてしまったりする。 これをLinuxは考慮してくれないので、場合によっては意地でもswapを使わないようにswapを切ってしまったほうが速く計算できるかもしれない。

もっとも、swapがあって困るケースは、私は暗号化以外には思いつかない。

また、一般的な利用ではハイバネーションのために、少なくともメモリと同容量以上のswapが必要である。swapがなければハイバネーションで退避させるスペースがないのでハイバネーションできない。

なお、swapをハイバネーションで使うにはさらなる追加パラメータが必要であり、設定が必要なのだが、最近のManjaro Linuxのインストーラー(Calamares)はハイバネーションするためにswapを使うための設定がある。

swapサイズは

Chris氏は大きいswapは悪いことはない、ということを説明している。 私もそう認識している。

ただし、Linux4.0以降に限る

しかし最近は物理メモリーが大きくなっている上に、高速でswapに適しているSSDの容量はそこまで大きくなっていないので、 256GBのSSDに128GBのswapを用意するみたいな話だとしんどいかもしれない。

swappinessは

swappinessは一般に「swapしやすさ」と理解されている。

いや、間違ってはいない。間違ってはいないのだが、ここでは fileページはswapされない という点を見失ってはいけない。

swapがあるとき、メモリを回収する必要があるならば、選択肢は主にふたつ。anonページをswapに追い出すか、fileページを解放するかだ。 前者は「swapを使う」ことになるし、後者は「fileページを捨てる」ことになる。どっちかをする必要があるのだから、言い換えれば、前者は「fileページをメモリ内に残す」という選択である。

つまり、swappinessは「fileページの代わりにanonページを解放する度合い」であるといえる。 全体200の中での割合であり、高くなればなるほどanonページの解放を優先するようになる。 そして、vm.swappiness = 0の場合は特別な方法でanonページのスキャンを避ける。