CPUボトルネックの原因を探る


表1.確認ポイントと項目

No 確認ポイント コマンドとオプション 確認する項目
@ ユーザとシステムCPUの合計が平均で70〜80%以上か? sar -u %usr、%sys
vmstat us、sy
mpstat usr、sys
A CPU待ちはあるのか? sar -q runq-sz
vmstat r
B ユーザとシステムCPUの比率は? sar -u %usr、%sys
vmstat us、sy
C どのプロセスがCPUを消費しているのか? prstat CPU
ps -efl | -efcl | -efcLl TIME | LTIME
timex/ptime real、user、sys
accton(採取開始と停止)
acctcom -f -m -t(編集)
REAL、USER、SYS
D 複数CPUの場合、排他制御のロック待ちになっていないか? mpstat smtx
E システムコール数は妥当か? sar -c scall/s
vmstat sy
F リード・ライトシステムコールの比率はどうか? sar -c sread/s、swrit/s
G プロセス実行のシステムコールはどうか? sar -c fork/s、exec/s
H プロセス間通信(IPC)システムコールはどうか? sar -m msg/s、sema/s
I コンテクストスイッチは妥当か? sar -w pswch/s
vmstat cs
J ディスク入出力との関係はどうか? sar -d %busy、avserv、avwait
iostat -xdn %b、svc_t、wait
K インタラプトが多発していないか? vmstat in
vmstat -i interrupt
mpstat intr
L NFSの状態はどうなっているのか? nfsstat  
M ディスク入出力待ちが大きいか? sar -u %wio

 

@ユーザとシステムCPUの合計が平均で70〜80%以上か?

定常的に、ユーザCPU使用率%usrと、システムCPU使用率%sysの合計が70〜80%の場合、CPU資源不足が考えられます。%usrと%sysの合計が100%であっても、CPU待ち(後述A)による処理の遅れが無い場合は問題ありません。これはCPUリソースを充分に消費している、すなわちCPUの使用効率が良いということになります。技術計算や配列操作の多いプログラムはこの傾向が強くなります。CPU待ちが高い場合、CPU資源が不足していると判断します。例では約5分間の高いCPU消費が見られます。この経過時間(elapsed time)が許容範囲かどうかが判断基準です。

解説 グラフ
定常的なユーザCPUとシステムCPU使用が認められます。この区間では、他のCPUを使用するプロセス(スレッド)は待たされます。
シナリオ番号:2 os(部分)

図1.CPU使用率


ACPU待ちはあるのか?

プロセス、またはスレッドが、メモリにロードされて実行可能であるのに、CPUの制御が与えられない場合、待ち行列にキューされます。このキューを示す値がsar コマンド-qオプションで表示される runq-sz です。vmstatコマンドでは r に相当します。参考文献1はCPU数の2倍以上、参考文献2はCPU数の4倍以上と、文献によって問題とする値に違いがあります。本コンテンツでは、CPU数プラス2以上を問題と考えます。理由としては、単一CPUの場合、そのCPU上でプロセス(A)が実行されているところに、次のCPUを使用するプロセス(B)が実行された場合、(B)は待ち行列に入れられるからです。新たなプロセス(B)のCPU処理は、先のプロセス(A)が中断されるまで待たされます。

解説 グラフ
複数のプロセスが待たされていることを示しています。トランザクション処理ではレスポンスが低下する要因になります。
シナリオ番号:2 os(部分)

図2.CPUの待ち


BユーザとシステムCPUの比率は?

過去、%usrと%sysのCPU使用比率は、1対1が理想と言われていました。この比率は、プログラムの処理方法によって大きな違いが出て来ます。このため、最近は、必ずしも1対1の比率では無くなっています。プログラムが技術計算、多くの配列操作や、レジスタを多用している結果、%usrが高い値を示している場合は問題ありません。また、NFSデーモンのように、カーネルCPUを多く使用するプロセスが実行されている場合も問題ではありません。例え、%usrと%sysの合計が100%であっても、CPU待ち(前述A)による処理の遅れが無い場合も問題ありません。これは、CPU資源を充分に消費している、すなわちCPU使用効率が良いということになります。判断基準としては、プログラムのロジックと相反する動作が認められる場合に問題となります。本来どうであるかを予め知っておくことが大切です。結果として、CPU待ちが高い場合、CPU資源不足と判断できます。

解説 グラフ
in.ftpd(サーバFTPデーモン)による動作です。%sysのみ使用されています。最初の山はSolaris←Linux(ftp起動側からファイルput)、次の山はSolaris→Linux(ftp起動側からファイルget)の振る舞いです。
シナリオ番号:3 os
CPU使用率は100%ではないにもかかわらず、CPU待ちが発生しています。これは、ユーザとカーネルスレッド、割り込みスレッド等の競合と考えられます。
シナリオ番号:3 os

図3.片寄ったCPU使用


CどのプロセスがCPUを消費しているのか?

デーモンのような常にメモリ上にロードされているプロセスを常駐プロセスと呼びます。常駐プロセスのCPU消費は、psやprstatコマンドで調べます。起動・終了するプログラムで、実行中にCPU消費時間を把握することが出来ないプロセスを非常駐プロセスと呼びます。非常駐プロセスのCPU消費は、timexやptimeコマンドで時間を調べます。timexやptimeコマンドが使用出来ない場合、プロセスアカウントを採取し、編集情報から値を得ます。表4.1に、これらステータスの採取方法をまとめました。

表4.1 プロセスのCPU消費時間を調べる

プロセス動作の区分 チェックするポイント 注意点
常駐しているプロセス。 prstatコマンドを実行してCPUフィールドを確認するか、またはpsコマンドを定期的に発行して、そのプロセスのTIME 、またはLTIMEフィールドの増加を見て下さい。 prstatコマンドは画面に表示される上位コマンドのCPU使用率を確認します。psコマンドの発行間隔(サンプリングインターバル)を例えば5秒とした場合、採取の開始と終了時の誤差が大きくなることに注意して下さい。並行してOSの性能情報を採取しておき、CPU以外のリソースに問題があるのかどうかを確認出来るようにして下さい。
起動・終了する非常駐プロセス。 timex、またはptimeコマンドを、目的のコマンドの先頭にセットして計測します。目的のコマンドが終了するとreal、sys、およびuserの時間が表示されます。それらの時間を確認して下さい。 並行してOSの性能情報を採取しておき、CPU以外のリソースに問題があるのかどうかを確認できるようにして下さい。
起動・終了するプロセスですが、コマンド起動時にtimex、ptimeが使えないもの。例えば、GUIより起動されるコマンドや、そのコマンドを起動するスクリプト類を修正出来ないようなものが該当します。 プロセスアカウンティングをacctonコマンドでオンし、目的の処理を実行します。所定の時間経過後、プロセスアカウンティングをオフし、acctcomコマンドで情報を編集して確認して下さい。 同上。

複数CPUが構成されているシステムでは、経過時間にCPU枚数を掛けたものが合計のCPU時間です。この合計に対して、常駐プロセスと非常駐プロセスのCPU使用時間がどうであるかが判断の基準になります。この式は次の通りになります。

CPU数×時間×平均のCPU使用率(パーセンテージ)≒常駐プロセスのCPU使用時間合計+非常駐プロセスのCPU使用時間合計

プログラムのロジックと相反する動作が認められる場合に問題となります。本来どうであるかを予め知っておくことが大切です。結果として、CPU待ちが高い場合、CPU資源不足と判断します。

解説 グラフ
ORACLEチェックポイントのバックグラウンドプロセスです。psコマンドの出力、TIME項目から抽出しました。ORACLE開始後、3秒のCPUを消費しています。
シナリオ番号:2 process(部分)

図4.常駐プロセスのCPU使用時間

 

表4.2 prstatの表示例

解説 データ
PID: プロセスIDです。
USERNAME: ユーザ名です。
SIZE: プロセスセグメントの合計です。この合計は共用コード、共有メモリ等、全てのセグメント合計が表示されます。値の末尾、"M"はメガバイト、"K"はキロバイト単位を示します。
RSS: メモリに常駐しているセグメントの合計です。SIZEと同様に、共用コード、共有メモリ等、全てのセグメント合計が表示されます。値の末尾、"M"はメガバイト、"K"はキロバイト単位を示します。
STATE: proc.hヘッダーファイルに定義されているプロセスの状態を示します。
PRI: プロセスの優先度です。大きな数字は高い優先度を示します。
NICE:ナイス値です。
TIME:プロセスの実行時間です。
CPU:プロセスで消費されたCPU時間の割り合いです。
PROCESS/NLWP:プロセス名と、スラッシュの後ろにLWPの数が表示されます。

Total: processes:現在のプロセス数合計です。
lwps:現在のLWP(スレッド)数合計です。
load averages:1分間、5分間、10分間のCPUロードアベレージです。
PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/NLWP
2743 oracle 417M 385M sleep 60 0 00:00.0 1.80% oracle/12
2727 oracle 421M 380M sleep 38 0 00:00.0 0.80% oracle/11
2731 oracle 415M 381M run 40 0 00:00.0 0.40% oracle/1
2725 oracle 418M 381M sleep 58 0 00:00.0 0.20% oracle/12
2720 oracle 12M 6688K sleep 45 0 00:00.0 0.20% sqlplus/4
2723 oracle 416M 380M sleep 58 0 00:00.0 0.20% oracle/1
2737 oracle 415M 379M sleep 0 0 00:00.0 0.10% oracle/1
2729 oracle 415M 379M sleep 58 0 00:00.0 0.10% oracle/1
2739 oracle 415M 379M sleep 0 0 00:00.0 0.10% oracle/1
2741 oracle 415M 379M sleep 0 0 00:00.0 0.10% oracle/1
2733 oracle 415M 378M sleep 50 0 00:00.0 0.10% oracle/1
2735 oracle 416M 379M sleep 0 0 00:00.0 0.10% oracle/1
2702 oracle 1056K 832K sleep 48 0 00:00.0 0.00% sh/1
2703 oracle 1056K 720K sleep 0 0 00:00.0 0.00% sh/1
398 root 28M 69M sleep 59 0 00:00.0 0.00% Xsun/1
2701 root 1512K 1352K cpu0 58 0 00:00.0 0.00% prstat/1
318 root 3496K 2240K sleep 58 0 00:00.0 0.00% vold/5
267 root 1440K 1120K sleep 58 0 00:00.0 0.00% powerd/5
219 root 2440K 1832K sleep 58 0 00:00.0 0.00% inetd/1
248 root 2952K 2296K sleep 58 0 00:00.0 0.00% nscd/7
254 root 3280K 1152K sleep 58 0 00:00.0 0.00% lpsched/1
Total: 72 processes 199 lwps, load averages: 0.12, 0.09, 0.05

 

表4.3 非常駐プロセスのCPU使用時間

解説 データ
プロセスアカウント情報から、

command:  コマンド名
userid:     ユーザID
elaps:     エラプス時間合計(秒)
callcount:   呼び出し回数
totalcpu:    CPU合計(秒)
rate%:     全体に占めるCPU時間の割合
syscpu:    システムCPU(秒)
sysmsec:   コマンド単位のシステムCPU(ミリ秒)
usercpu:    ユーザCPU(秒)
usermsec:   コマンド単位のユーザCPU(ミリ秒)

にまとめたものです。

usercpuで逆ソートし、0.3秒以上をリストしました。

acctcomコマンドの出力から、コマンド名の出現回数をカウントするとともに、当該コマンド名のREAL、CPU部分の時間を累積し、最後に、「累積値を出現回数で割った値」がsysmsecusermsecです。
command userid elaps callcount totalcpu rate% syscpu sysmsec usercpu usermsec
awk oracle 288.91 27360 117.62 9.80 70.12 2.56 47.50 1.74
oracle oracle 12,330.19 133 37.88 3.16 6.72 50.53 31.16 234.29
echo oracle 275.46 27403 79.38 6.61 53.82 1.96 25.56 0.93
tst
【備考】
root 90.05 2 47.60 3.97 30.92 15,460.00 16.68 8,340.00
sed oracle 133.90 10745 39.52 3.29 24.41 2.27 15.11 1.41
dd root 78.63 1 42.16 3.51 31.78 31,780.00 10.38 10,380.00
orado.ed oracle 310.80 1 16.07 1.34 10.75 10,750.00 5.32 5,320.00
sqlplus oracle 112.21 94 6.67 0.56 1.91 20.32 4.76 50.64
awk root 17.15 1325 7.61 0.63 3.92 2.96 3.69 2.78
ps root 39.05 273 6.58 0.55 3.31 12.12 3.27 11.98
netstat root 2,471.69 485 5.72 0.48 3.23 6.66 2.49 5.13
expr oracle 16.98 1685 5.46 0.45 3.13 1.86 2.33 1.38
nawk oracle 15.40 1506 5.73 0.48 3.44 2.28 2.29 1.52
echo root 26.21 2240 5.58 0.46 3.88 1.73 1.70 0.76
rm oracle 22.65 1545 5.10 0.42 3.68 2.38 1.42 0.92
sed root 12.02 958 3.60 0.30 2.37 2.47 1.23 1.28
vmstat root 2,452.85 245 2.18 0.18 1.21 4.94 0.97 3.96
orado.sh oracle 331.73 18 1.25 0.10 0.57 31.67 0.68 37.78
exp oracle 5.54 1 0.81 0.07 0.14 140.00 0.67 670.00
sleep root 6,060.28 967 1.67 0.14 1.04 1.08 0.63 0.65
pmap root 36.37 128 1.46 0.12 0.92 7.19 0.54 4.22
head root 4.39 349 1.56 0.13 1.03 2.95 0.53 1.52
expr root 2.92 284 1.09 0.09 0.56 1.97 0.53 1.87
cat oracle 5.28 504 1.53 0.13 1.04 2.06 0.49 0.97
tail oracle 6.31 626 1.82 0.15 1.34 2.14 0.48 0.77
sort root 2.59 211 1.02 0.09 0.55 2.61 0.47 2.23
#in.ftpd root 152.88 1 10.83 0.90 10.42 10,420.00 0.41 410.00
wc oracle 3.05 300 0.89 0.07 0.49 1.63 0.40 1.33
nawk root 1.90 95 0.66 0.06 0.28 2.95 0.38 4.00
sardo.ed root 32.86 4 1.00 0.08 0.65 162.50 0.35 87.50
#crash root 0.73 2 0.60 0.05 0.27 135.00 0.33 165.00
ls oracle 2.48 193 0.76 0.06 0.44 2.28 0.32 1.66
ps oracle 0.75 33 0.63 0.05 0.32 9.70 0.31 9.39
シナリオ番号:2 pacct.info(部分)
【備考】メモリを掃除するスィープコマンド(作成プログラム)です。後に、"sweep"に名前を変えました。


D複数CPUの場合排他制御のロック待ちになっていないか?

マルチスレッドや、複数CPUの環境では、メモリ内容を更新する際、排他制御によって一貫性を保つ仕組みを持っています。これを排他制御(ミューテックスロック)と呼びます。CPUがラッシュ状態になると、排他制御が頻繁に発生し、ロック待ちが発生することがあります。ロック待ちを示す値はmpstatコマンドで表示される項目smtxです。参考文献1では500以上、参考文献2ではCPU数×250倍を問題としています。もしこの値が異常に高い場合に、ハードウェア的なシステム増強を検討する際、CPUの枚数を増やすのではなく、CPUそのものを速いもの(例えばクロック数の大きいもの)にすべきです。この理由は、smtxが高い状態でCPU枚数を増やすと、ロック待ちの機会が指数階乗的に増加するからです。

解説 グラフ
単一CPUでもこのような値が記録されることがあります。ユーザとカーネルスレッド、またはユーザと割り込みスレッドの競合が発生しているものと考えられます。
シナリオ番号:3 cpu

図5.排他ロック


Eシステムコール数は妥当か?

あらゆるシステムコールの秒あたり回数は、sarコマンド-cオプションのscall/sで示されます。scall/sは、リード・ライト、プロセス起動・実行、セマフォ制御などのシステムコール全部の秒あたり実行数が含まれます。プログラムの性質、アプリケーションの作り等で大きな差が出ます。このため、妥当性を判断するには、通常どのような値であるのか、予め知っておくことが大切です。

解説 グラフ
15:44:43より、ddコマンドのbs=16384で1ギガバイトのファイルを作成しました。波が低いのでやや見づらいです。15:46:33より、ddコマンドのbs=512で1ギガバイトのファイルを作成しました。ブロック化係数が変化することで、システムコール数が大幅に増加しています。
シナリオ番号:4 os

図6.システムコール


Fリード・ライトシステムコールの比率はどうか?

一般的に、バッチ処理は大量のデータを処理するため、ディスクのリード・ライトシステムコールが多いです。トランザクション処理は、ディスク入出力を最適化することによって、リード・ライトのシステムコールは抑えられるべきです。このように、アプリケーションの動作や処理の違いによって、システムコールに占めるリード・ライトシステムコールの率は変わってきます。したがって、リード・ライトシステムコール比率の妥当性は、通常どのようなものであるかを知っておくことが大切です。プログラムのロジックと相反する動作が認められる場合に問題となります。

解説 グラフ
ddコマンドで、1ギガバイトのファイルを作成しました。ブロックサイズを示すbsパラメタに16384を指定することにより、ブロックサイズは16384バイト/1ブロックとなります。リード・ライトのシステムコールは約800回/秒の水準になります。この結果、scall/sに占めるリード・ライトのシステムコール比率は43パーセントになりました。
シナリオ番号:4 os(部分)
ddコマンドで、1ギガバイトのファイルを作成しました。ブロックサイズは、512バイト/1ブロックとなります。リード・ライトのシステムコールは約28000回/秒の水準になります。この結果、scall/sに占めるリード・ライトのシステムコール比率は96パーセントになりました。
シナリオ番号:4 os(部分)

図7.リード・ライトシステムコールの比率


Gプロセス実行のシステムコールはどうか?

UNIXでは、新たなプロセスを生起する時、forkシステムコールによって子プロセスを発生させ、続いて、発生した子プロセス自身が、目的の実行プログラムをexecシステムコールによって起動します。この過程で、メモリを始めとして、ファイルオープン識別子、各種の制御テーブル等を大量に割り当てることから、処理に多くのコストがかかることが知られています。シェルスクリプトを中心にした処理では、fork/execシステムコールが高くなります。マルチスレッド環境は、このプロセス生起の手順とは別の方法で、スレッドを発生させることにより、低コストで目的の処理を実行する仕組みを提供しています。このため、TPモニターのようなトランザクション処理システムは、スレッド化された構造を持つことが多く、fork/execシステムコールの比率が低いようです。プログラムの性質、アプリケーションの作り等で大きな差が出ます。このため、妥当性を判断するには、通常どのような値であるのか予め知っておくことが大切です。

解説 グラフ
16:18:34から約30秒間、および16:27:30からの5分間はシェルスクリプト、コマンドを多用したプログラムが実行されています。fork/sとexec/sの比率が高くなっています。16:16:44から約90秒はddコマンドによるリード・ライトシステムコールです。
シナリオ番号:2 os

図8.プロセス実行のシステムコール


Hプロセス間通信(IPC)システムコールはどうか?

プロセス間通信(IPC:Inter Process Communication)は、プロセスとプロセスの間でデータをやり取りする仕組みで、System V IPCと呼ばれています。IPCの機能は、共有メモリ、メッセージキュー、およびセマフォの3種類です。共有メモリは、同じメモリ空間を別プロセスが読み書きできる機能です。メッセージキューは、メッセージと呼ばれるデータの単位をプロセス間で送受信する機能です。セマフォ(semaphore:腕木信号機のことです)はプロセス間でセマフォ値と呼ばれる信号の交換を行うことで、プロセスの同期を取ったり、排他制御を行う機能です。TPモニターのようなトランザクション処理システムや、データベースソフトウェアで多く使用されています。sarコマンド-mオプションは、メッセージキューとセマフォの秒あたり操作数を表示します。システムコールに占めるIPCコールの割り合いが多い場合、CPU資源を多く使用することがあります。他のシステムコールと同様に、プログラムの性質、アプリケーションの作り等で大きな差が出ます。このため、妥当性を判断するには、通常どのような値であるのか予め知っておくことが大切です。また、IPC関連のチューニングは大切です。

解説 グラフ
ORACLE STATSPACKの起動と、レポート作成時に、秒あたりのセマフォ操作数が高くなっています。
シナリオ番号:2 os

図9.プロセス間通信(IPC)


Iコンテクストスイッチは妥当か?

プロセス(スレッド)が他のプロセス(スレッド)、またはカーネルにCPU制御を移すことをコンテクストスイッチと呼びます。システムコールが多用されていたり、割り込みが多く発生したような場合、関連してコンテクストスイッチの値が高くなることがあります。プログラムの性質、アプリケーションの作り、および機器構成等で大きな差が出ます。このため、妥当性を判断するには、通常どのような値であるのか、予め知っておくことが大切です。

解説 グラフ
ORACLEのセマフォ制御時が最もコンテクストスイッチが高くなっています。
シナリオ番号:2 os

図10.コンテクストスイッチ


Jディスク入出力との関係はどうか?

ユーザプロセスがCPU上で計算処理を行っている最中、それより前にライトされたデータをディスクに書き込み中、という場面は多くあります。ディスクにデータ転送を終えて書き込みが終了すると割り込みが起き、割り込み処理が行われます。そのCPU上で行われていたユーザの計算処理は、一旦中断します。割り込み処理がまたたく間に終了し、中断していたユーザCPUの処理が継続する…CPUは100%使用され、ディスク入出力はその間に終わっているというのが並行処理の理想です。一方、CPUの計算処理を終え、処理結果データをディスクに書き込む。続いて、ディスクの書き込み終了を待っている。即ち、入出力待ち%wioが発生する。このような状況は、CPU処理の観点からもったいないものです。このタイムラグを抑えるために、ディスクバッファキャッシュの機構があります。次に、ブロック化係数の違いで%wioを記録する状態と、CPUをより多く使用する顕著な例を示します。

解説 グラフ
15:44:43は、ddコマンドのbs=16384で1ギガバイトファイルを作成した時のCPU使用状況です。%wioが発生しており、ディスクの待ちが発生しています。15:46:33は、ddコマンドのbs=512で1ギガバイトファイルを作成した時のCPU使用状況です。%usrと%sysが高くなっています。
シナリオ番号:4 os
%usrと%sysの高まりは、リード・ライトシステムコールと、データのブロック詰めによるものです。エラプス時間は約20秒余分にかかっています。bs=16384がCPUリソースを消費していないので得だと分かります。%wioが無くなるのが理想ですが…
シナリオ番号:4 os
ディスクのビジーです。
ブロックサイズが大きい場合=%busyは高い
ブロックサイズが小さい場合=%busyは低い
となります。

シナリオ番号:4 disk

図11.ディスク入出力との関係


Kインタラプトが多発していないか?

滅多にないことですが、割り込みが急激に発生した結果スローダウンになることがあります。ハードウェアトラブルか、またはネットワーク攻撃の可能性があります。

解説 グラフ
CPU0の割り込みです。この例は、ftpで他の機器からget要求が来たものです。本シナリオのサンプリングインターバルは5秒ですから、秒あたり5〜600パケットが送受信されています。ネットワークのみならず、ディスク関連のインタラプトも数えられます。SYN flood等の攻撃では、このような数ではなく、とんでもない数になります。
シナリオ番号:2 cpu
時計はいつも安定しています…
シナリオ番号:2 cpu

図12.インタラプト


LNFSの状態はどうなっているのか?

N/A


Mディスク入出力待ちが大きいか?

%wioが定常的に30パーセントを超えると、ディスク入出力、またはメモリに何らかの問題があります。まず、「ディスク入出力」をご覧下さい。

解説 グラフ
16:02頃から16:04頃、および16:05頃から16:06:30頃まで高い%wioが記録されています。本シナリオでは、メモリ不足が原因でページングが頻繁になり、ディスク入出力が高負荷になっているものです。
シナリオ番号:7 os


Copyright (C) 2004 by The Art of Computer Technologies, Corp.  All rights reserved.