profile プロバイダは、時間ベースの割り込みに関連付けられていて、指定された間隔 (固定) で起動するプローブを提供します。これらのアンカーされていないプローブは、特定の実行ポイントではなく非同期割り込みイベントに関連付けられています。これらのプローブでは、単位時間ごとにシステム状態の標本を収集できます。こうして収集された標本は、システムの動作を推測するのに役立ちます。サンプリングレートが高いときや、サンプリング時間が長いときは、正確な推測が可能です。DTrace アクションを使用すると、profile プロバイダにより、システム内のあらゆるデータの標本を収集できます。たとえば、現在のスレッドの状態、CPU の状態、現在のマシンの命令などの標本を収集できます。
profile プロバイダのプローブからスレッド固有変数にアクセスすることはできません。そのようなプローブで特殊な識別子 self を使ってスレッド固有変数を参照しても、何も出力されません。
profile-n プローブは、各 CPU 上で、固定の間隔で起動します。割り込みレベルが高いという特徴があります。n はプローブの起動間隔を表しています。割り込みソースは、毎秒 n 回起動します。n には、時間の単位を表す接尾辞を付加できます。表 19–1 に、有効な接尾辞とその意味を示します。
表 19–1 有効な時間接尾辞|
「サフィックス」 |
時間の単位 |
|---|---|
|
nsec または ns |
ナノ秒 |
|
usec または us |
マイクロ秒 |
|
msec または ms |
ミリ秒 |
|
sec または s |
秒 |
|
min または m |
分 |
|
hour または h |
時間 |
|
day または d |
日 |
|
hz |
ヘルツ (秒当たりの回数) |
以下の例では、97 ヘルツで起動し、現在実行中のプロセスの情報を収集するプローブを作成します。
#pragma D option quiet
profile-97
/pid != 0/
{
@proc[pid, execname] = count();
}
END
{
printf("%-8s %-40s %s\n", "PID", "CMD", "COUNT");
printa("%-8d %-40s %@d\n", @proc);
}
この例をしばらく実行すると、次の例のような出力が得られます。
# dtrace -s ./prof.d ^C PID CMD COUNT 223887 sh 1 100360 httpd 1 100409 mibiisa 1 223887 uname 1 218848 sh 2 218984 adeptedit 2 100224 nscd 3 3 fsflush 4 2 pageout 6 100372 java 7 115279 xterm 7 100460 Xsun 7 100475 perfbar 9 223888 prstat 15 |
実行中のプロセスの情報は、profile-n プロバイダでも収集できます。次の D スクリプト例では、1,001 ヘルツのプロファイルプローブを使って、指定されたプロセスの現在の優先順位に関する情報を収集します。
profile-1001
/pid == $1/
{
@proc[execname] = lquantize(curlwpsinfo->pr_pri, 0, 100, 10);
}
このスクリプト例の動作を確認するには、まず、ウィンドウ内に次のコマンドを入力します。
$ echo $$ 12345 $ while true ; do let i=0 ; done |
別のウィンドウで D スクリプトを短時間間実行します。このとき、 12345 を echo コマンドから返された PID に置き換えてください。
# dtrace -s ./profpri.d 12345
dtrace: script './profpri.d' matched 1 probe
^C
ksh
value ------------- Distribution ------------- count
< 0 | 0
0 |@@@@@@@@@@@@@@@@@@@@@ 7443
10 |@@@@@@ 2235
20 |@@@@ 1679
30 |@@@ 1119
40 |@ 560
50 |@ 554
60 | 0
|
タイムシェアリングスケジューリングクラスの分布状況が出力されます。シェルプロセスは CPU 上でスピン中なので、システムによる優先順位は常に低い状態です。シェルプロセスの実行頻度がさらに低ければ、優先順位は高くなります。この結果を確認するには、スピン中のシェルで Control-C キーを入力し、先ほどのスクリプトを再度実行します。
# dtrace -s ./profpri.d 494621 dtrace: script './profpri.d' matched 1 probe |
次に、同じシェルに何か文字を入力します。DTrace スクリプトを終了すると、次のような出力が得られます。
ksh
value ------------- Distribution ------------- count
40 | 0
50 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 14
60 | 0
|
シェルプロセスは、CPU 上でスピンせず、ユーザー入力を待ってスリープしていました。このため、実際に実行されたときの優先順位がより高くなっています。
tick-n プローブは、profile-n プローブと同じように、割り込みレベルが高く、固定の間隔で起動します。しかし、profile-n プローブのように各 CPU で起動するわけではありません。tick-n プローブは、毎回 1 個の CPU 上で起動します。実際の CPU は、時間の経過とともに変化します。profile-n プローブの場合と同じように、n はデフォルトでは秒当たりのレートですが、時間を表す接尾辞 (オプション) を付けることもできます。tick-n プローブには、定期的な出力、定期的なアクションの実行など、いくつかの用途があります。
|
arg0 |
プローブが起動したときのカーネル内のプログラムカウンタ (PC)。プローブが起動したとき、カーネル内で現在のプロセスが実行されていなかった場合はゼロになります。 |
|
arg1 |
プローブが起動したときのユーザーレベルのプログラムカウンタ (PC)。プローブが起動したとき、カーネル内で現在のプロセスが実行されていた場合はゼロになります。 |
この説明からわかるように、arg0 がゼロ以外の値の場合 arg1 はゼロ、arg0 がゼロの場合 arg1 はゼロ以外になります。この特性を利用すると、arg0 と arg1 を使ってユーザーレベルとカーネルレベルを区別できます。以下に例を示します。
profile-1ms
{
@ticks[arg0 ? "kernel" : "user"] = count();
}
profile プロバイダは、オペレーティングシステム内の任意の分解能のタイマーを使用します。任意の分解時間ベースの割り込みを完全にサポートしないアーキテクチャでは、周波数が、カーネル変数 hz で指定されたシステムクロックのクロック周波数によって制限されます。こうしたアーキテクチャーでは、hz より周波数が高いプローブは、1/hz 秒ごとに何回か起動します。たとえば、こうしたアーキテクチャで hz が 100 に設定されている場合、1000 ヘルツの profile プローブは、10 ミリ秒ごとに連続してすばやく 10 回起動します。任意の分解能をサポートするプラットフォームでは、1000 ヘルツの profile プローブは、ミリ秒ごとに 1 回ずつ起動します。
以下は、アーキテクチャの分解能をテストする例です。
profile-5000
{
/*
* We divide by 1,000,000 to convert nanoseconds to milliseconds, and
* then we take the value mod 10 to get the current millisecond within
* a 10 millisecond window. On platforms that do not support truly
* arbitrary resolution profile probes, all of the profile-5000 probes
* will fire on roughly the same millisecond. On platforms that
* support a truly arbitrary resolution, the probe firings will be
* evenly distributed across the milliseconds.
*/
@ms = lquantize((timestamp / 1000000) % 10, 0, 10, 1);
}
tick-1sec
/i++ >= 10/
{
exit(0);
}
任意の分解能の profile プローブをサポートするアーキテクチャでは、このスクリプトを実行すると、 結果は均一の分布になります。
# dtrace -s ./restest.d
dtrace: script './restest.d' matched 2 probes
CPU ID FUNCTION:NAME
0 33631 :tick-1sec
value ------------- Distribution ------------- count
< 0 | 0
0 |@@@ 10760
1 |@@@@ 10842
2 |@@@@ 10861
3 |@@@ 10820
4 |@@@ 10819
5 |@@@ 10817
6 |@@@@ 10826
7 |@@@@ 10847
8 |@@@@ 10830
9 |@@@@ 10830
|
任意の分解能の profile プローブをサポートしないアーキテクチャでは、このスクリプトを実行すると、 結果は均一の分布になりません。
# dtrace -s ./restest.d
dtrace: script './restest.d' matched 2 probes
CPU ID FUNCTION:NAME
0 28321 :tick-1sec
value ------------- Distribution ------------- count
4 | 0
5 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 107864
6 | 424
7 | 255
8 | 496
9 | 0
|
こうしたアーキテクチャで、実効プロファイルの分解能を改善するには、/etc/system ファイルを手作業で編集して、hz の値をチューニングします。
現在、すべての UltraSPARC (sun4u) は、任意の分解能の profile プローブをサポートしています。多くの x86 アーキテクチャ (i86pc) も、任意の分解能の profile プローブをサポートしていますが、バージョンの古いものの中には、一部サポートしないものもあります。
profile プロバイダは、ほかのプロバイダとは違って、必要に応じて動的にプローブを作成します。dtrace -l -P profile などを実行したとき、表示される全プローブのリストに必要なプロファイルプローブが含まれていない場合がありますが、このプローブは、明示的に有効にすると作成されます。
任意の分解能の profile プローブをサポートするアーキテクチャでは、時間間隔が短すぎると、マシンは時間ベースの割り込みの処理に追われることになります。その結果、マシンの本来のサービスが妨害されます。この問題を防ぐため、profile プロバイダは、200 マイクロ秒未満の間隔になるプローブの作成を拒否します。このとき、メッセージは表示されません。
以下の表に、profile プロバイダの安定性を DTrace の安定性機構に従って示します。安定性機構の詳細については、第 39 章安定性を参照してください。
|
要素 |
名前の安定性 |
データの安定性 |
依存クラス |
|---|---|---|---|
|
プロバイダ |
発展中 |
発展中 |
共通 |
|
モジュール |
変更の可能性あり |
変更の可能性あり |
不明 |
|
機能 |
非公開 |
非公開 |
不明 |
|
名前 |
発展中 |
発展中 |
共通 |
|
引数 |
発展中 |
発展中 |
共通 |