Linuxのスワップ処理を最適化するためのヒント

 コンピュータのメモリ容量を超えるサイズのプログラムを実行する必要がある場合、最近のオペレーティングシステム(OS)のほとんどはスワップ処理と呼ばれる手法を用いる。これは、メモリ内データの大部分を一時的にハードディスクに格納しておき、必要なデータだけを物理メモリ空間に持ってくるというものだ。本稿では、Linuxシステムにおけるスワップ処理の効率化とスワップ処理サブシステムのパフォーマンス最適化につながるテクニックを紹介する。

 Linuxは、物理メモリの領域をページという単位に分割して処理する。スワップ処理とは、ハードディスク上にあらかじめ設定した空間(これをスワップ空間と呼ぶ)にページ単位でメモリ上のデータをコピーし、そのページのメモリ領域を解放する処理をいう。物理メモリとスワップ空間を合わせた容量が、仮想メモリとして利用可能になる。

 スワップ処理が必要になる主な理由は2つある。1つは、物理的に使えるメモリ容量以上の領域がシステムで必要になった場合に、あまり使われていないページをメモリからハードディスクに移動(スワップアウト)させ、メモリを直ちに必要とする実行中のアプリケーション(プロセス)にそのメモリ領域を与える、というカーネルでの対処を可能にするためだ。もう1つは、アプリケーションの起動時に初期化のために使用された大量のページがその後まったく使われない場合で、システムはそうしたページをスワップアウトしてメモリを解放し、その領域をほかのアプリケーション、場合によってはディスクキャッシュに割り当てることが可能になる。

 しかし、スワップ処理には1つ弱点がある。メモリに比べ、ディスクの読み書きが非常に遅いことだ。物理メモリのアクセス速度の測定がナノ秒単位で行われるのに対し、ディスクはミリ秒単位なので、ディスクへのアクセスには物理メモリの何万倍もの時間がかかっていることになる。スワップ処理の発生が増えるほど、システムの速度が低下するわけだ。同じページのスワップアウトとスワップイン(ハードディスクに移したデータを再びメモリに戻すこと)が短時間のうちに繰り返されると、過剰なスワップ処理、つまりスラッシングが起こることがある。そうした状況では、システムが空いているメモリ領域を探しつつアプリケーションの実行を続けようとするため、相当な負荷がかかる。この問題を回避するには、物理メモリを増やすしかない。

 Linuxには、スワップパーティションとスワップファイルという2つの形態のスワップ空間がある。スワップパーティションは、スワップ処理のためだけに使用されるハードディスク上の独立したセクションである。よって、それ以外のファイルをそこに置くことはできない。スワップファイルはLinuxファイルシステム上の特別なファイルで、システムファイルおよびデータファイルと同じような形で存在する。

 確保されているスワップ空間を確認するには、「swapon -s」コマンドを使用する。その出力結果は次のようになる。

Filename        Type            Size    Used    Priority
/dev/sda5       partition       859436  0       -1

 このように、システムで使用されているスワップ空間が1行ずつ表示される。上記の‘Type’フィールドはこのスワップ空間がファイルではなくパーティションであること、‘Filename’フィールドはファイルがsda5というディスク上にあることを示している。‘Size’にはそのスワップ空間のサイズが、‘Used’にはそのうちどれだけ使用されているか(この場合はまったく使用されていない)が、それぞれキロバイト単位で表示される。また、‘Priority’はLinuxがスワップ空間を使用するときの優先順位を示す。Linuxのスワップ処理サブシステムがすばらしいのは、2つ以上のスワップ空間(別々のデバイスに確保するのが望ましい)を同じ優先順位にしてマウントした場合、それらの間でスワップ処理動作を並列実行(インターリーブ)してくれることだ。これにより、スワップ処理のパフォーマンスは大幅に向上する可能性がある。

 システムにスワップパーティションを追加するには、まずパーティションの準備を行う必要がある。そのパーティションがスワップパーティションとして設定されていることを確認したうえで、スワップファイルシステムの作成を行うことになる。パーティションがスワップ用になっていることを確認するには、次のようなコマンドをrootで実行する。

fdisk -l /dev/hdb

 ‘/dev/hdb’の部分は、スワップパーティションが設定されている各自のハードディスクのデバイス名で置き換えること。出力結果は次のようになるはずだ。

 Device Boot    Start   End     Blocks  Id      System
/dev/hdb1       2328    2434    859446  82      Linux swap / Solaris

 パーティションがスワップとして表示されていない場合は、fdiskの実行でメニューオプションの‘t’を選択してスワップ用に設定し直す必要がある。ただし、パーティション設定の作業は慎重に行うこと。重要なパーティションを誤って削除したり、システムパーティションのIDをうっかりスワップ用に変更したりはしたくないはずだ。スワップパーティション上の全データが失われる場合には、変更箇所をすべて再度チェックすること。また、SolarisのパーティションにはLinuxのスワップ空間と同じIDが使用されるので、誤ってSolarisパーティションを消さないようにも注意が必要だ。

 パーティションをスワップ用に設定したら、次のようなmkswap(スワップ作成)コマンドをrootで実行して、スワップパーティションの作成を行う。

mkswap /dev/hdb1

 何もエラーが出なければ、スワップ空間の準備は完了だ。スワップ空間を直ちに有効にするには、次のコマンドを実行すればよい。

swapon /dev/hdb1

 スワップ空間の使用状況は「swapon -s」を実行すれば確認できる。また、ブート時に自動的にスワップ空間をマウントするには、「/etc/fstab」ファイルへのエントリの追加が必要だ。このファイルはブート時にマウントされるファイルシステムとスワップ空間のリストになっていて、それぞれの行は次の形式で記述されている。

<ファイルシステム>     <マウントポイント>     <タイプ>     <オプション>        <ダンプ間隔>    <パス番号>

 スワップ空間は特殊なタイプのファイルシステムなので、これらのパラメータの多くは適用できない。スワップ空間の場合は、次のように記述する。

/dev/hdb1       none    swap    sw      0       0

 ‘/dev/hdb1’がスワップパーティション名である。スワップには特定のマウントポイントがないため、その部分は‘none’となっている。タイプは‘swap’、オプションは‘sw’、また使用しない最後の2つのパラメータは‘0’にしておく。

 スワップ空間が自動マウントされることをリブートせずに確認するには、「swapoff -a」(すべてのスワップ領域を無効化)と「swapon -a」(「etc/fstab」ファイルに記されたすべてのスワップ空間をマウント)を順に実行したうえで、「swapon -s」コマンドでそのスワップ空間がマウントされていることを確認すればよい。

スワップファイル

 Linuxはスワップパーティションだけでなくスワップファイルもサポートしており、その作成、準備、マウントはスワップパーティションと同様の形で行える。スワップファイルの利点は、スワップ空間を追加するために空のパーティションを探したり、ハードディスクのパーティションを切り直したりする必要がないことだ。

 スワップファイルを作成するには、ddコマンドを使って空のファイルを作成する。たとえば、サイズを1GBにする場合は次のように入力する。

dd if=/dev/zero of=/swapfile bs=1024 count=1048576

 ‘/swapfile’はスワップファイル名、‘1048576’という値はファイルサイズ(1GB)をキロバイト単位で指定したものだ。

 スワップファイルの準備にはパーティションのときと同じmkswapコマンドを使用するが、今回は次のようにスワップファイル名を指定する。

mkswap /swapfile

 そして、パーティションの場合と同様、「swapon /swapfile」というコマンドを使ってマウントを行う。

 なお、スワップファイルの場合、「/etc/fstab」ファイルのエントリは次のように記述する。

/swapfile       none    swap    sw      0       0

スワップはどれくらいにすべきか

 Linuxシステムはスワップ空間がなくても動作し、十分なメモリがあれば問題は起こらない。しかし、物理メモリを使い果たしてしまうと何もできなくなってクラッシュしてしまう。したがって、スワップ空間は用意しておくことが望ましい。なんといっても、ディスク領域はメモリよりも安価だ。

 ここで問題になるのが、そのサイズである。以前のUNIX系OS(Sun OSやUltrix)では、物理メモリの2~3倍のスワップ領域が必要だった。最近実装されたもの(Linuxなど)ではそこまでスワップを必要としないが、それくらいのサイズに設定することは可能だ。だいたいの目安は次のようになる。

  1. 一般的なデスクトップマシンの場合はシステムメモリの2倍にあたるスワップ領域を確保する。これで多数のアプリケーションを実行しても(その多くはアイドル状態にあって容易にスワップ処理が行えるので)アクティブなアプリケーションでより多くのメモリが使えるようになる。
  2. サーバの場合は利用可能なスワップの容量を少なめに取る(たとえば物理メモリの半分)。これは、いざとなったらスワップを柔軟にコントロールするためで、スワップ使用量を監視して必要であればメモリの増強を行う。
  3. 旧式のデスクトップマシン(メモリが128MBしかないものなど)では1GBまでの範囲で確保できるだけのスワップ領域を設定する

 Linuxカーネル2.6ではswappinessという新たなカーネルパラメータが追加され、管理者によるLinuxのスワップ処理の調整が可能になっている。このパラメータには0~100の値を設定するが、要は値が大きいほどページのスワップ処理が増え、値が小さいほど多くのメモリ領域がアプリケーションによって(たとえアイドル状態であっても)確保されるということだ。カーネルメンテナのAndrew Morton氏は、swappinessを100にして自らのデスクトップマシンを動作させたうえでこう述べている。「肝心なのは、カーネルによるスワップ処理を減らすのは良くないという点だ。負荷の大きなアプリによって何百メガバイトものメモリが確保されたまま、マシン上で有効に活用されない状態は何としても避けたいと思うだろう。そんな領域はディスク上に追い出し、空いたメモリを有効に使うべきだ」

 だが、Morton氏の考え方には、メモリ領域のスワップアウトが早すぎるとアプリケーションの応答が悪くなるというマイナス面もある。これは、(それまで使っていた)アプリケーションの画面をクリックしてもそのアプリケーションのデータが(すでにスワップアウトされて)メモリ内になければ、システムはそのデータを再びメモリに呼び戻さなければならず、その時間分の遅延が生じるからだ。

 swappinessのデフォルト値は60だが、rootとして次のコマンドを実行することにより、この設定を一時的に(次回リブートまで)変えることができる。

echo 50 > /proc/sys/vm/swappiness

 また、変更を持続させるには「/etc/sysctl.conf」ファイル内のvm.swappinessパラメータを変更する必要がある。

まとめ

 スワップ空間の管理は、システム管理において欠かせない部分だ。十分に検討してうまく利用すれば、スワップ処理によって多くのメリットが得られる。とにかく、怖がらずにスワップを設定してシステムのパフォーマンスを計測し、望みどおりの結果が得られるかどうかを確認してみることだ。

Gary Simsは英国の大学でビジネス情報システムの学位を取得。10年に及ぶソフトウェアエンジニアとしての活動を経て、現在はフリーランスのLinuxコンサルタント兼ライター。

Linux.com 原文