第8章 KSM

最近のオペレーティングシステムでは共有メモリーという概念が一般的になってきました。たとえば、プログラムが初めて起動する際に、そのプログラムはその親プログラムとすべてのメモリーを共有します。子プログラムまたは親プログラムのいずれかがメモリーの変更を試行すると、カーネルによって新しいメモリー領域が割り当てられ、元のコンテンツがコピーされます。これにより、プログラムがこの新たな範囲を変更できるようになります。これがコピーオンライト (copy on write) と呼ばれるものです。
KSM はこの概念を逆に応用した Linux の新しい機能になります。KSM により、カーネルはすでに実行中の複数のプログラムを検査し、それらのメモリーを比較することができます。メモリーの領域またはページがまったく同一である場合は、KSM は複数ある同一メモリーページを 1 つのページに減らし、このページにはコピーオンライトのマークが付けられます。ページのコンテンツがゲスト仮想マシンによって変更された場合は、そのゲスト仮想マシン用に新しいページが作成されます。
KSM は KVM を使った仮想化に便利です。ゲスト仮想マシンの起動時に、ゲスト仮想マシンは親の qemu-kvm プロセスからのメモリーしか継承しません。同じオペレーティングシステムやアプリケーションを複数のゲストが実行している場合、ゲスト仮想マシンがゲスト仮想マシンのオペレーティングシステムのコンテンツを実行し始めると、イメージを共有することができるようになります。KSM はまったく同一のページのみを識別し、マージします。このため、ゲスト仮想マシンが干渉されたり、ホスト物理マシンやゲストの安全に影響を与えることはありません。KSM の機能によって KVM は同一のゲスト仮想マシンのメモリー領域が共有されるよう要求することができます。
KSM によってメモリーの速度やその用途が広がります。KSM を使用すると、共通の処理データはキャッシュやメインメモリーに格納されます。これにより KVM ゲストのキャッシュミスが低減するため、一部のアプリケーションやオペレーティングシステムのパフォーマンスを向上させることができます。また、メモリーを共有することにより、ゲストの全体的なメモリー使用を抑えるため、より多くのリソースを有効に活用できるようになります。

注記

Red Hat Enterprise Linux 6.5 より、KSM は NUMA 対応になりました。これにより、ページコアレッシングの実行時に NUMA ローカリティーが考慮されることになり、リモートノードに移行されるページに関連するパフォーマンスの低下を防ぐことができるようになります。Red Hat は、KSM の使用時にはノード間のメモリーマージを控えることを推奨します。KSM が使用中の場合には、/sys/kernel/mm/ksm/merge_across_nodes 調整可能パラメーターを 0 に変更し、複数の NUMA ノード間でのページのマージを防ぎます。多量のノード間マージが実行されると、カーネルメモリーのアカウンティング統計は相反する結果となる可能性があります。そのため、numad も KSM デーモンが多量のメモリーをマージした後に混乱する可能性があります。システムに大量の空きメモリーがある場合、KSM デーモンをオフにし、無効にすることでパフォーマンスを向上させることができます。NUMA についての詳細は、『Red Hat Enterprise Linux パフォーマンスチューニングガイド』 を参照してください。
Red Hat Enterprise Linux では、KSM の管理に以下の 2 種類の方法を使用しています。
  • ksm サービス: KSM カーネルスレッドの起動と停止を行います。
  • ksmtuned サービス: ksm の制御と調整を行い、同じページのマージを動的に管理します。この ksmtuned サービスは ksm を起動し、メモリー共有が必要ない場合には ksm サービスを停止します。新規のゲストが作成されたり、ゲストが破棄された場合には、retune パラメーターを使い、この ksmtuned サービスに対して実行の指示を出さなければなりません。
いずれのサービスも標準のサービス管理ツールで制御されます。
KSM サービス

ksm サービスは qemu-kvm パッケージに含まれています。Red Hat Enterprise Linux 6 の KSM はデフォルトではオフになっています。 ただし、Red Hat Enterprise Linux 6 を KVM ホスト物理マシンとして使用する場合は ksm/ksmtuned サービスによってオンになる可能性があります。

ksm サービスを起動していない場合は、KSM で共有されるページは 2000 ページのみになります。このデフォルト値ではページ数が少ないため、メモリー節約で得られる利点も限られます。
ksm サービスを起動すると、KSM は最大でホスト物理マシンシステムのメインメモリーの 50% まで共有するようになります。ksm サービスを起動して KSM がより多くのメモリーを共有できるようにします。
# service ksm start
Starting ksm:                                              [  OK  ]
ksm サービスをデフォルトのスタートアップ順序に追加することができます。chkconfig コマンドを使って ksm サービスを永続化します。
# chkconfig ksm on
KSM チューニングサービス

ksmtuned サービスにはオプションがありません。ksmtuned サービスはループして ksm の調整を行います。ゲスト仮想マシンが作成されたり、破棄された場合は、libvirt によって ksmtuned サービスに通知されます。

# service ksmtuned start
Starting ksmtuned:                                         [  OK  ]
ksmtuned サービスは retune パラメーターを使って調整できます。retune パラメーターの指示によって ksmtuned は手動によるチューニング機能を実行します。
ファイル内のパラメーターを変更する前に、以下の用語を明確に理解しておく必要があります。
  • thres - キロバイト単位のアクティブ化しきい値です。thres 値とすべての qemu-kvm プロセスによって消費されるメモリー量である RSZ 値の合計がシステムメモリーの合計を上回ると、KSM サイクルがトリガーされます。このパラメーターは、KSM_THRES_COEF に定義されるパーセンテージをキロ単位で表したものと同等です。
/etc/ksmtuned.conf ファイルは ksmtuned サービスの設定ファイルになります。デフォルトの ksmtuned.conf ファイルの出力を以下に示します。
# Configuration file for ksmtuned.

# How long ksmtuned should sleep between tuning adjustments
# KSM_MONITOR_INTERVAL=60

# Millisecond sleep between ksm scans for 16Gb server.
# Smaller servers sleep more, bigger sleep less.
# KSM_SLEEP_MSEC=10

# KSM_NPAGES_BOOST is added to the npages value, when free memory is less than thres.
# KSM_NPAGES_BOOST=300

# KSM_NPAGES_DECAY Value given is subtracted to the npages value, when free memory is greater than thres.
# KSM_NPAGES_DECAY=-50

# KSM_NPAGES_MIN is the lower limit for the npages value.
# KSM_NPAGES_MIN=64

# KSM_NAGES_MAX is the upper limit for the npages value.
# KSM_NPAGES_MAX=1250

# KSM_TRES_COEF - is the RAM percentage to be calculated in parameter thres.
# KSM_THRES_COEF=20

# KSM_THRES_CONST - If this is a low memory system, and the thres value is less than KSM_THRES_CONST, then reset thres value to KSM_THRES_CONST value.
# KSM_THRES_CONST=2048

# uncomment the following to enable ksmtuned debug information
# LOGFILE=/var/log/ksmtuned
# DEBUG=1
KSM の変数とモニタリング

KSM はモニタリングデータを /sys/kernel/mm/ksm/ ディレクトリーに格納します。このディレクトリー内のファイルはカーネルによって更新されるため、KSM の使用量と統計値の正確な記録となります。

以下に示す変数も /etc/ksmtuned.conf ファイル内にある設定可能な変数となります。

/sys/kernel/mm/ksm/ 以下のファイル

full_scans
実行された完全スキャン数
pages_shared
共有されたページの合計数
pages_sharing
現在共有されているページ数
pages_to_scan
スキャンされなかったページ数
pages_unshared
共有されなくなったページ数
pages_volatile
揮発性のページ数
run
KSM プロセスが実行しているかどうか
sleep_millisecs
スリープのミリ秒数
/etc/ksmtuned.conf ファイルに DEBUG=1 の行を追加すると、KSM チューニングのアクティビティーが /var/log/ksmtuned ログファイルに格納されます。LOGFILE パラメーターを使用するとログファイルの場所を変更することができます。ただし、ログファイルの場所を変更すると、SELinux 設定に特殊な設定が必要となる場合があるため、この変更はお勧めできません。
KSM の無効化

KSM にはパフォーマンス上のオーバーヘッドがあり、特定の環境やホスト物理マシンシステムには負荷が大きすぎる場合があります。

ksmtunedksm サービスを停止すると KSM を非アクティブ化することができます。これらのサービスの停止により KSM は非アクティブ化されますが、再起動後は元に戻ります。
# service ksmtuned stop
Stopping ksmtuned:                                         [  OK  ]
# service ksm stop
Stopping ksm:                                              [  OK  ]
再起動後も KSM の非アクティブな状態を永続化するには、chkconfig コマンドを使用します。 サービスをオフにするには次のコマンドを実行します。
# chkconfig ksm off
# chkconfig ksmtuned off

重要

KSM を使用する場合であっても、コミットする RAM に対して swap サイズの大きさが十分であることを確認してください。KSM は同一または同様のゲストの RAM 使用量を低減します。十分な swap 領域がなくても KSM を使ってゲストをオーバーコミットすることはおそらく可能ですが、ゲスト仮想マシンのメモリー使用によってページが共有されなくなる可能性があるため推奨されません。