CPUの性能分析事例紹介
表1.ポイントと項目
No | ポイント | 内容 |
@ | シェルコマンドをCプログラム化する | 一般に、シェルスクリプトを使用したプログラムは、CPUを多く消費することがあります。システム性能管理でよく用いられる、CPUロードアベレージを得るコマンドw(1)と、uptime(1)、および数式を評価するexpr(1)コマンドを例に、CPU消費がどのように変化するのかを紹介します。 |
A | ディスパッチャテーブルをチューニングする | 他のSVR4システムで用いられていたTSディスパッチャテーブルをSolarisに適用して、CPU消費がどのように変化するのかを紹介します。 |
B | C++の処理をawk(1)コマンドで代替する | C++プログラムによるDBローダーバッチプログラムを、awk(1)コマンドに置き換えて、500時間かかった処理をわずか30分に短縮した事例を紹介します。 |
本コンテンツの冒頭で述べましたが、システムパフォーマンスチューニングは、アプリケーションの作りを良くすることと、ハードウェア構成を見直すことがポイントです。この例では、シェルで使用されるコマンドをCでコーディングしたプログラムにすることによって、どのようにCPU消費が変化するのかを見てみます。例として、図1.1のようなシェルスクリプトを使用します。wコマンドの出力を、/dev/nullに10000回出力するサンプルシェルスクリプトです。
#!/bin/sh N=1 COUNT=10000 while [ $N -le $COUNT ] do w > /dev/null N=`expr $N + 1` done |
図1.1 サンプルシェルスクリプト
wコマンドは、システム稼働時間、最近の1分、5分、10分のCPUロードアベレージ、およびログオンしているユーザ情報を表示します。図1.2にwコマンドの出力例を示します。
# w <CR> 3:12pm up 1:39, 4 users, load average: 5.20, 2.37, 0.96 User tty login@ idle JCPU PCPU what oracle pts/2 1:41pm 3:09 -csh nuruki pts/3 3:07pm 1 w nuruki pts/4 3:10pm 2 55 1 /bin/sh /export/nuruki/bin/cpu12 nuruki pts/5 3:10pm 2 16 1 /bin/sh /export/nuruki/bin/cpu13 # |
図1.2 wコマンドの出力例
仮に、wコマンドの1行目に表示されるCPUロードアベレージだけを使用して、システム性能管理に応用する場合、ログオンユーザ情報は不要のため、sedやawkコマンドを用いてデータを加工することになります。このような場合、wコマンドの1行目のみを出力するuptimeコマンドを用いると、ログオン情報を捨てる必要は無くなります。図1.3はuptimeコマンドの出力例です。ログオン情報は表示されません。
# uptime <CR> 3:13pm up 1:40, 4 users, load average: 4.63, 2.54, 1.07 # |
図1.3 uptimeコマンドの出力例
ここで、システム管理の目的が、CPUロードアベレージのみ必要とします。すると、uptimeコマンドの出力に含まれるシステム稼動時間等の情報は不要です。uptimeコマンドのCPUロードアベレージを表示する他の方法は無いのかを調査すると、ライブラリコールがこれに対応していることが分かりました。図1.4にCPUロードアベレージを表示するCプログラムを示します。
#include <sys/loadavg.h> main () { double loadavg[3]; getloadavg(loadavg,3); printf("%.2f %.2f%.2f\n",loadavg[LOADAVG_1MIN],loadavg[LOADAVG_5MIN],loadavg[LOADAVG_15MIN]); } |
図1.4 CPUロードアベレージ表示プログラム
図1.1の、whileループの最後にあるexprコマンドは、数式を評価してその結果を標準出力に表示するコマンドです。本サンプルでは単に足し算に使用しているものです。これもCプログラムで書き直してみます。図1.5に足し算のCプログラムを示します。
#include <stdio.h> main(int argc, char *argv[]) { int i,o; i=atoi(argv[1]); o=i+atoi(argv[2]); printf("%d\n",o); } |
図1.5 足し算プログラム
これらを組み合わせて、サンプルシェルスクリプトを実行した結果を図1.6に示します。時間測定はtimexコマンドを使用しました。
No | シェルスクリプト | 変更内容 | real | user | sys | 効果 |
1 | while [ $N -le $COUNT ] do w > /dev/null N=`expr $N + 1` done |
図1.1のオリジナルサンプルシェルスクリプト。 | 3:18.81 | 46.66 | 2:24.77 | - |
2 | while [ $N -le $COUNT ] do w > /dev/null N=`add $N 1` done |
exprコマンドをaddコマンドに変更。 | 3:11.88 | 44.08 | 2:20.47 | やや向上 |
3 | while [ $N -le $COUNT ] do uptime > /dev/null N=`expr $N + 1` done |
wコマンドをuptimeコマンドに変更。 カウントはexprコマンドを使用。 |
1:33.19 | 31.77 | 56.08 | 約50%向上 |
4 | while [ $N -le $COUNT ] do average > /dev/null N=`add $N 1` done |
wコマンドをaverageコマンドに変更。 カウントはaddコマンドを使用。 |
55.20 | 16.36 | 34.49 | 約72%向上 |
図1.6 Cプログラム化の効果
これらコマンドにどれだけのCPU時間が使用されたのかを、プロセスアカウント情報からピックアップしてみました。表1.1にコマンドのCPU使用時間を示します。テストシナリオ番号は41です。
表1.1 コマンドのCPU使用時間
command | elaps | callcount | totalcpu | syscpu | sysmsec | usercpu | usermsec |
w | 174.96 | 10000 | 168.54 | 131.77 | 13.1770 | 36.77 | 3.6770 |
uptime | 101.20 | 10000 | 55.09 | 34.75 | 3.4750 | 20.34 | 2.0340 |
average | 100.51 | 10000 | 23.77 | 16.28 | 1.6280 | 7.49 | 0.7490 |
expr | 101.74 | 10087 | 28.24 | 16.80 | 1.6655 | 11.44 | 1.1341 |
add | 201.29 | 20000 | 47.75 | 31.48 | 1.5740 | 16.27 | 0.8135 |
以上のように、特定目的のコマンドをCプログラム化することで、システムの高速化を図ることができます。ちりも積もれば山になるのです…
参考文献2では、プロセス優先度を固定するとともに、TS(タイムシェアリング)ディスパッチャテーブルを部分的に変更してフェンスオフ(囲い込み)する手法が述べられています。ここでは、全体的なディスパッチャテーブルの変更によって、プロセスのCPU使用がどのように変化するのかを紹介します。テーブルは、他のUNIX SVR4で採用されていたものです。各々の違いは、SolarisのTSディスパッチャテーブル、およびSVR4のTSディスパッチャテーブルをご覧ください。図2にCPUに特化した処理の振る舞いの違いを示します。
テーブル | CPU使用状況 | コンテクストスイッチ |
Solarisの TSテーブル |
シナリオ番号:41 os |
シナリオ番号:41 os |
SVR4の TSテーブル |
シナリオ番号:45 os |
シナリオ番号:45 os |
図2.ディスパッチャテーブルの違いによるCPU使用状況の変化
CPU使用状況に大きな違いは見えませんが、sarコマンド-wオプションで示されるpswch/s(コンテクストスイッチ)に違いが認められます。最初のCPUの山で、SolarisのTSディスパッチャテーブルの場合、約1500回/秒であったのが、SVR4のTSディスパッチャテーブルを使用すると、約1300回/秒に減っています。処理はwコマンドを10000回ループするもので、カウンタはadd(@のコマンドをCプログラム化するをご覧ください)プログラムを使用しています。次のCPUの山、および最後のCPUの山に対応するコンテクストスイッチに、大きな変化は見られません。SVR4のディスパッチャテーブルはts_quantumのティック数が大きい点が特徴で、プロセス(スレッド)に与えられるタイムクォンタムが長くなり、コンテクストスイッチの機会が減ります。この効果は、CPU使用時間の長いプロセスに現れることになります。表2はテストシナリオ番号41と45のプロセスアカウント情報をまとめたものです。CPU使用時間の長いwコマンドで効果が現れていることがわかります。
表2.ディスパッチャテーブルの違いによるCPU使用状況
テーブル | データ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Solarisの TSテーブル |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SVR4の TSテーブル (1回目) |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SVR4の TSテーブル (2回目) |
|
現在のSolaris TSディスパッチャテーブルは、プライオリティ59番目(TSで最も優先度の高いところ)のts_maxwaitに、32000ティックが与えられており、待ちが充分に長いこと、およびts_quantumに小さいティック値がセットされていることから、コンテクスト切り替えを多くして、プロセス(スレッド)に公平にCPU時間を与えるように設定されています。
T.B.D
Copyright (C) 2004 by The Art of Computer Technologies, Corp. All rights reserved.