さて、今回は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);
}
}
このプログラムは引数で指定された数だけの子プロセスを生成し、自身と各子プロセスが大きさ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の手順としては第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
次にシステムの稼働情報を取得するわけだが、プログラムの実行によってシステムの動作が不安定になることは分かっているため、投入前と後のデータを取得して比較を行うことにする。取得するデータは仮想メモリ状況、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秒間隔で実行し、プロセスの稼働状況をログに記録
準備が整ったら実行例3のようにプログラムを実行する。これで現象発生中のデータが取得できるはずだ。
# ./swaptest 12 &
: ← リスト1中で太字で示したprintfが実行されたら再度swaptestを実行
# ./swaptest 12 &
:
:
# killall swaptest ←問題の現象が確認されたらkillallで停止させる
さて、ここまでで現象発生中のデータが取得できた。次回では、このデータを使い、ステータスの解釈やデータ分析方法に足を踏み入れていこう。
本記事は、オープンソースマガジン2006年2月号「Linux PD−問題判別脳力養成道場」を再構成したものです。
Copyright © ITmedia, Inc. All Rights Reserved.