発生した遅延の原因がスワップによるI/Oにある、と分かったところで、今度はこの事象が実際にはどのプロセスに大きく影響を与えていたか、topの出力データを使って確認してみよう。なお、プロセスへの影響度を測るには各pid*ごとに総実行時間を算出すれば良いが、これはtopの出力からは難しいため、先に述べたvmstatでbフィールドにカウントされているブロック状態のプロセスを特定してみよう。なお、プロセスの総実行時間を得る場合、topを使用するのではなくtimeコマンドを利用するのが確実である。
図3は取得したtop実行結果の一部である。topの各項目の意味は表3やmanページを参照してほしい。
topの出力からブロックされているプロセスを特定するには、STATフィールドのプロセス状態を示すステータスが「D」となっているプロセスを探せば良い。図3では幾つかのswaptestプロセスがブロックされていることが分かる。
今回のケースではスワップがボトルネックになっているわけだが、これと結びつけられるデータがもう1つ確認できる。STATがDとなっているswaptestと、Sとなっているswaptestでは、RSS、つまり使用している物理メモリサイズが大きく異なっている点である。
swaptestプログラム自体は各子プロセス当たり10Mバイトのメモリアロケーションを行う。一方、STATがSとなっているswaptestのRSSはプログラムどおりの10Mバイトであるが、DとなっているswaptestのRSSは10Mバイトに満たないのである。
これらから、次のような現象が発生しているということが分かる。
このとき、STATがDとなったプロセスはI/Oが終了し、メモリが利用できるようになるまで実行再開ができないため遅延が発生するのである。
スワップに関するボトルネックの解消には、以下の3つの方法が効果的である。
Linuxにおけるスワップ処理は主にカーネルプロセスのkswapdが行うが、しばしば性能面でのパフォーマンス劣化が取りざたされる。カーネル2.6になってページ参照のアルゴリズムは大幅に進歩し、その効果も上がってはいるものの、スワップ周りの性能を構成面、設計面で配慮するに越したことはない。
1の「スワップデバイスの分散」は、単にパーティーションやディスクを分割するのではなく、デバイスのコントローラーやチャネルを分割するほか、バスの帯域やコントローラーキャッシュを分散することで物理ディスクへのI/O性能を考慮することを示唆している。
2の「メモリの追加」は、物理メモリ領域の枯渇状態を軽減し、スワップそのものを減少させることを目的としている。
3の「プロセス単位のメモリ使用量削減」は、必要なデータセグメント*を最小限にするプログラム設計や起動プロセスの削減、子プロセスのスレッド化などが該当する。
2回にわたってシステムに負荷をかけた状態で発生する遅延、というトラブルケースをシミュレーションし、実際にツールを使ってPDを行う例を紹介した。また、ツールの使用方法だけでなく、ステータスの解釈やデータ分析方法にも足を踏み入れている。もちろん、今回の例が問題のすべてではないし、実際に発生するさまざまなケースでは、その状況によって解釈や分析結果も変わってくる。そのため、トラブルを実際に作らなくとも日々のオペレーションやベンチマーク時などにリソース情報を収集し、カーネルの挙動を理解することをお勧めする。
次回はカーネルのプロファイリングを取り上げ、より深いシステム内部の動きを観察する予定だ。
Process ID。各プロセスが固有に持つID。
プログラム中で使用するデータが格納されるメモリ領域。
本記事は、オープンソースマガジン2006年2月号「Linux PD−問題判別脳力養成道場」を再構成したものです。
Copyright © ITmedia, Inc. All Rights Reserved.