第5回 PDツールでシステムの内部情報に迫れ【前編】障害発生時の金科玉条(2/2 ページ)

» 2007年03月22日 10時00分 公開
[秋田英行(日本アイ・ビー・エム),ITmedia]
前のページへ 1|2       

パフォーマンス劣化問題をシミュレートする

 さて、今回はPDにおけるツールの利用方法を理解してもらうため、簡単なシミュレーションを行ってみたいと思う。このシミュレーションで「CPUとメモリに負荷をかけた場合にシステムはどのような挙動を起こすのか」ということを体験していただきたい。

 まず、CPUおよびメモリに負荷をかけるツールを用意する。CPUとメモリに負荷がかかればどのようなものでも良いが、今回はリスト1のような、簡単な自作サンプルプログラムを使用した。


#include 

#define BUF_SIZE (1024 * 1024) #define MAX_INDEX 10 #define MAX_COUNT 10
main(int argc, char *argv[]) {   int pid, id;   char *tbl[MAX_INDEX];   int count = 0;   int i;
  if(argc > 1)     count = atoi(argv[1]);   if(count <= 0)     count = MAX_COUNT;
  for(id = 0; id < count; id++)   {     if ((pid=fork()) == -1)       exit(1);     if (pid == 0)       break;     printf("%02d: pid=%d\n", id, pid);   }
  pid = getpid();   for(i = 0; i < MAX_INDEX; i++ )   {     tbl[i] = (char *)malloc(BUF_SIZE);   }   while(1)   {     for(i = 0; i < MAX_INDEX; i++)     {       bzero(tbl[i], BUF_SIZE-1);     }     printf("%02d: pid=%d, i=%d\n", id, pid, i);     sleep(2);   } }
リスト1 サンプルプログラム「swaptest.c」。太字部分の部分は実行例3で

 このプログラムは引数で指定された数だけの子プロセスを生成し、自身と各子プロセスが大きさBUF_SIZEのメモリ領域をMAX_INDEX回割り当てて、そのメモリ領域にゼロを入れる、といった処理を繰り返すプログラムだ。この例ではBUF_SIZEが1Mバイト、MAX_INDEXが10であるため、コマンドの引数に20を渡すと親プロセスと20個の子プロセス、計21個のプロセスがそれぞれ10Mバイト、合計で210Mバイトのメモリを配列として確保し、強制終了させるまでその配列にゼロを埋める処理を行ってCPUを消費し続ける、という動作を行う。このプログラムを次のようにコンパイルし、swaptestを作成する。

$ gcc -o swaptest swaptest.c


 また、このプログラムの実行に当たってシステムの挙動を分かりやすくするため、システム全体で使用するメモリサイズを256Mバイトに、CPU数を1に指定した。これはLinux起動時に「mem=256M」と「maxcpus=1」をカーネルパラメータとして与えれば良い。

プログラムの実行

 さて、それではこのプログラムを実行してみよう。今回はswaptestプログラムを2つ、段階的に実行することでシステムの挙動の変化を観察する。与える引数は環境によって異なると思うが、今回の例では引数を12とするとコンソール入力やsshセッションに体感できるほどの遅延が発生した。

 さて、この「遅延」という現象は、実際には何が原因で発生しているのだろうか? PDを行ってみよう。

コンソールの遅延問題をPDする

 PDの手順としては第1回でも解説したとおり、

  1. 状況把握
  2. 情報収集
  3. データ分析
  4. 解決を図る

というのが一般的だ。それらを踏まえ、今回のシミュレーションを行っていこう。

ステップ1 構成情報の確認

 PDに必要な構成情報を実行例1のように取得する。このシミュレーションのテーマは「プログラムによる負荷がシステムに与える影響の観察」であるため、詳細なハードウェアの構成情報などは取得していない。

cat /proc/cpuinfo  ←CPU情報の取得
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 8
model name      : Pentium III (Coppermine)
stepping        : 6
cpu MHz         : 797.542
cache size      : 256 KB
        :
        :
# head -n 5 /proc/meminfo  ←メモリ情報の取得
total:    used:    free:  shared: buffers:  cached:
Mem:  260218880 26763264 233455616        0  1916928 11431936
Swap: 4293586944 15331328 4278255616
MemTotal:       254120 kB
MemFree:        227984 kB
# fdisk -l  ←HDDパーティション情報の取得
Disk /dev/sda: 36.4 GB, 36401479680 bytes
255 heads, 63 sectors/track, 4425 cylinders
Units = シリンダ数 of 16065 * 512 = 8225280 bytes
 デバイス ブート  始点       終点  ブロック   ID  システム
/dev/sda1    *       1         13    104391   83  Linux
/dev/sda2           14        535   4192965   82  Linux スワップ
/dev/sda3          536       3146 20972857+   83  Linux

実行例1 システム構成情報の取得

ステップ2 データの取得

 次にシステムの稼働情報を取得するわけだが、プログラムの実行によってシステムの動作が不安定になることは分かっているため、投入前と後のデータを取得して比較を行うことにする。取得するデータは仮想メモリ状況、I/O状況、プロセスの使用状況の3つだ。これらの取得は実行例2のように行う。

vmstat 1 >> vmstat.log & ←1秒間隔で仮想メモリ使用状況をログに記録
# iostat -x -t 1 >> iostat.log & ←1秒間隔でI/O状況をログに記録
# (while true; do top -b -n 1 >> top.log; sleep 1; done) &
↑topを1秒間隔で実行し、プロセスの稼働状況をログに記録

実行例2 仮想メモリ、I/O、プロセスの稼働状況を取得

 準備が整ったら実行例3のようにプログラムを実行する。これで現象発生中のデータが取得できるはずだ。


# ./swaptest 12 &
        : ← リスト1中で太字で示したprintfが実行されたら再度swaptestを実行
# ./swaptest 12 &
        :
        :
# killall swaptest ←問題の現象が確認されたらkillallで停止させる

実行例3 シミュレーション実施

 さて、ここまでで現象発生中のデータが取得できた。次回では、このデータを使い、ステータスの解釈やデータ分析方法に足を踏み入れていこう。

本記事は、オープンソースマガジン2006年2月号「Linux PD−問題判別脳力養成道場」を再構成したものです。


前のページへ 1|2       

Copyright © ITmedia, Inc. All Rights Reserved.

注目のテーマ