スワップ
このページでは GNU/Linux でのスワップ領域とページングを紹介します。また、スワップパーティションとスワップファイルの作成と有効化について説明しています。
All about Linux swap space より:
- Linux は物理 RAM (random access memory) をページと呼ばれるメモリのかたまりに分割します。スワッピングとは、メモリを解放するために、ページがスワップ領域という名の事前設定領域にコピーされることを言います。物理メモリとスワップ領域の合計が利用できる仮想メモリのサイズになります。
スワップのサポートは Linux カーネルにより提供され、ユーザスペースのユーティリティは util-linux パッケージに存在します。
目次
スワップ領域
スワップ領域は普通ディスクパーティションとして作られますが、ファイルにすることもできます。Arch Linux のインストール中にユーザーはスワップ領域を作成することができ、必要であればインストール後でも作成できます。スワップ領域を作成する理由は2つあります: 仮想メモリを拡張して、搭載している物理メモリ(RAM)より多くするためと、suspend-to-disk(ハイバネート) をするためです。
スワップを使って仮想メモリを拡張することが利益になるかどうかは搭載している物理メモリの容量により異なります。必要なプログラムをすべて実行するのに必要な量の物理メモリを搭載していないのであれば、スワップを作成することはおそらく利益となるでしょう。これにより、out of memory(メモリ不足) を避けることができます。Out of memory とは、Linux カーネルの OOM killer という仕組みが自動的にプロセスを kill してメモリの空き領域を作ろうとしている状態のことを言います。仮想メモリの容量を必要な量まで増やすには、足りない分をスワップ領域として追加してください。
メモリが枯渇しているときにスワップを使用することの最大の欠点は、パフォーマンスが低下することです(#パフォーマンス セクションを見てください)。それゆえ、スワップを有効化するかどうかは個人の好みの問題となります。スワップを有効化するよりメモリが枯渇したときにプロセスが kill されるほうが良いという人もいますし、メモリが枯渇したときにシステムが低速化するがスワップを有効化したほうが良いという人もいます。
スワップの状態を確認するには、次を実行:
$ swapon --show
もしくは、以下を実行して物理メモリとスワップの使用状況を表示:
$ free -h
スワップパーティション
スワップパーティションは、ほとんどの GNU/Linux のパーティショニングツールで作成することができます。スワップパーティションは、GPT 上ではパーティションタイプ GUID 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F
が (gdisk では 8200
タイプ、fdisk では swap
タイプ)、MBR 上ではタイプ ID 82
が指定されています。
Linux のスワップ領域をセットアップする時には、mkswap(8) コマンドが使われます。例えば:
# mkswap /dev/sdxy
デバイスのページングを有効にするには:
# swapon /dev/sdxy
オプションについては swapon(8) を参照してください。
起動時に有効化する
スワップパーティションをブート時に有効化するには:
- systemd#GPT パーティションの自動マウントを使う
- あるいは、
/etc/fstab
にエントリを追加する。例:UUID=device_UUID none swap defaults 0 0
device_UUID
はスワップ領域の UUID です。
fstab
ファイルの構文については fstab を見てください。また、systemd#systemd.mount - マウント も参照してください。
スワップの無効化
特定のスワップ領域を無効にするには:
# swapoff /dev/sda2
もしくは -a
スイッチを使って全てのスワップ領域を無効化することもできます。
スワップは systemd によって管理されているため、次の起動時にスワップが自動的に有効化されてしまいます。検出されたスワップ領域を自動的に有効化する機能を恒久的に無効にするには、systemctl --type swap
を実行して問題の .swap ユニットを確認してマスクしてください。
スワップファイル
パーティションを作るかわりに、臨機応変にサイズを変えたり簡単に削除できるものとしてスワップファイルが選択肢になりえます。特にディスク容量が貴重な場合 (例: 小容量の SSD) はこちらが理想的でしょう。
ファイルシステム | スワップファイルのサポート |
---|---|
Bcachefs | No |
Btrfs | Yes |
F2FS | Yes |
ext4 | Yes |
JFS | Yes |
NILFS2 | No |
NTFS3 | Yes |
ReiserFS | Yes |
XFS | Yes |
ZFS | No |
スワップファイルの作成
mkswap(8) を使用して、所望のサイズのスワップファイルを作成します (ヒントは パーティショニング#スワップ を参照してください)。たとえば、4 GiB のスワップファイルを作成します:
# mkswap -U clear --size 4G --file /swapfile
スワップファイルを有効化してください:
# swapon /swapfile
最後に、fstab 設定を編集してスワップファイルのエントリを追加してください:
/etc/fstab
/swapfile none swap defaults 0 0
fstab にエントリを追加する以外に、スワップユニットを作成する方法もあります (systemd.swap(5) を参照):
/etc/systemd/system/swapfile.swap
[Swap] What=/swapfile [Install] WantedBy=swap.target
作成後は daemon-reload を実行し、swapfile.swap
を有効化してください。
追加の情報については fstab#使用法 を見てください。
スワップファイルの削除
スワップファイルを削除するには、まずスワップファイルを無効にしなければなりません。その後、スワップファイルを削除できます:
# swapoff /swapfile # rm -f /swapfile
最後に /etc/fstab
から該当するエントリを削除してください。
スワップの暗号化
dm-crypt/スワップの暗号化を見て下さい。
パフォーマンス
通常、スワップに対する操作は RAM 上のデータに対する直接アクセスよりも断然遅くなります。しかし、パフォーマンスを向上させようとしてスワップを全体的に無効化するとパフォーマンスの劣化を招くことがあります。データを保持しておくのに十分な物理メモリが無い場合、スワップアウトできないとファイルシステムキャッシュのためのメモリが足りなくなってしまいます。その結果、ディスクへのアクセスが増加し、負荷が増加します。
スワップ値を変えることでパフォーマンスを向上できるかもしれません。
Swappiness
メモリ使用量が特定の閾値に達すると、カーネルはアクティブなメモリを調べ、何を解放できるかを確認し始めます。ファイルデータは (変更されている場合) ファイルシステムに書き出して、アンロードし、後で再ロードすることができます。他のデータは、アンロードする前にスワップに書き込まなければなりません。
Swappiness sysctl パラメータは、カーネルが書き込み先としてファイルよりもスワップを優先する度合いを表します。Swappiness は 0 から 200 の間の値にすることができます (Linux < 5.8 では 100 が最大)。デフォルトの値は 60 です。小さい値にすると、カーネルは開いているファイルの解放を優先し、大きい値にすると、カーネルはスワップ領域を使おうとします。100 にすると、IO コストが等しいとみなされます。
現在の swappiness 値をチェックするには:
$ sysctl vm.swappiness
代わりに /proc/sys/vm/swappiness
ファイルを読むことで生の整数値を得ることができます。
swappiness 値を一時的にセットするには:
# sysctl -w vm.swappiness=35
swappiness 値を永続的にセットするには、sysctl.d(5) 設定ファイルを作成します。例えば:
/etc/sysctl.d/99-swappiness.conf
vm.swappiness = 35
ブートローダーを使ってカーネルのロード時に swappiness を設定するには、カーネルパラメータを追加してください。例えば: sysctl.vm.swappiness=35
。
他の swappiness 値を選択する理由としては以下があります:
- デスクトップの応答性のために swappiness を下げることが提案されているから。この主張の言わんとしていることは、知覚されるパフォーマンス (応答性) はプログラムがユーザーの入力にいかに速く応答するかによるため、anonymous ページ (プログラムのメモリ) は RAM 内に留めておくべきであり、実際のパフォーマンスを多少犠牲にしてでも開いたファイルの解放を優先させるべきというものです。
- 妥当な swappiness の最小値は 1 です。Swappiness を 0 にすると、anonymous ページのエビクションに対して極端なバイアスが掛かり、メモリ争奪の極端な状況を除いて anonymous ページを reclaim やスワップするためにスキャンできなくなります。全く使用されていない anonymous ページを reclaim しないことは一般に望ましくありません。
- 100 以上の高い swappiness に設定することは、スワップする IO コストがファイルからの読み出しコストと同じかより小さい場合に (定義上) 望ましいから。このような状況はスワップがディスクをバッキングデバイスとして使用していない場合 (特に zram を使用している場合) に起こり得ます。また、スワップ IO が zswap などの低コストなメカニズムによってインターセプト/キャッシュされる場合にも起こり得ます。
VFS cache pressure
スワップのパフォーマンスに影響を与えるもう1つの sysctl パラメーターは vm.vfs_cache_pressure
です。このパラメータは、ページキャッシュとスワップと比較して、VFS キャッシュのキャッシングのために使用されているメモリをカーネルが reclaim する優先度を制御します。この値を増やすと、VFS キャッシュが reclaim される割合が上がります。このパラメータの詳細は Linux カーネルのドキュメントを参照してください。
デフォルトの値は 100 です。この場合、ファイルシステムのキャッシュは他のキャッシュと同じくらい重要ということになり、両方のキャッシュは同じ重みで reclaim されます。デスクトップでは、ファイルシステムのブラウジング時間は操作のレイテンシ (知覚される応答性) に影響を与えるからファイルシステムのキャッシュは他のキャッシュよりも重要であるため、VFS cache pressure は 50 に設定するべきと主張されています。一方、VFS キャッシュに二度とアクセスされない多くの小さなファイルのメタデータが保持されている場合、より大きな値に設定することが提案されています。このパラメータのチューニングに関する詳細は OpenSUSE のチューニングガイドを参照してください (このガイドでは、キャッシュのタイプを slaptop
でチェックし実験することが推奨されています)。
優先度
複数のスワップファイルやスワップパーティションを使っている場合、priority 値 (0 から 32767) をそれぞれのスワップ領域に割り当てることを考えて下さい。システムは優先度が低いスワップ領域を使う前に高い優先度が付けられたスワップ領域を使います。例えば、もしあなたが高速なディスクと低速なディスクを持っている場合、高速なデバイス上のスワップ領域に高い優先度をあててください。priority は fstab で pri
パラメータを使って設定できます:
UUID=f9fe0b69-a280-415d-a03a-a32752370dee none swap defaults,pri=100 0 0 UUID=d7eb6062-01c8-4367-ac1d-3bf1167de8bb none swap defaults,pri=10 0 0
もしくは swapon の --priority
パラメータを使います:
# swapon --priority 100 /dev/sda1
もし2つ以上の領域が同じ priority を持ち、それが一番高い priority の場合、その領域間ではラウンドロビン方式でページが配分されます。
ストライピング
スワップの性能を上げるために RAID を使う必要はありません。/etc/fstab
ファイルでスワップの優先度が同じに設定されている場合、複数のデバイスにスワップをストライプ処理するのはカーネルだけで行うことができます。詳しくは The Software-RAID HOWTO を参照してください。
Discard (トリム)
ソリッドステートドライブ#スワップ を参照。
RAM 内の圧縮ブロックデバイス
パフォーマンスの向上#zram や zswap でのスワップ を参照。
スワップ領域をハイバーネート専用に使う
スワップをハイバネートイメージストレージ領域としてしか使わない場合、zswap を使い、そのライトバックを無効化することで、通常のスワップ仕様ではディスク書き込みが起こらないようにすることができます。電源管理/サスペンドとハイバネート#Zswap のライトバックを無効化し、スワップ領域をハイバネートのみに使用する を参照してください。