Solaris 動的トレースガイド

第 19 章 profile プロバイダ

profile プロバイダは、時間ベースの割り込みに関連付けられていて、指定された間隔 (固定) で起動するプローブを提供します。これらのアンカーされていないプローブは、特定の実行ポイントではなく非同期割り込みイベントに関連付けられています。これらのプローブでは、単位時間ごとにシステム状態の標本を収集できます。こうして収集された標本は、システムの動作を推測するのに役立ちます。サンプリングレートが高いときや、サンプリング時間が長いときは、正確な推測が可能です。DTrace アクションを使用すると、profile プロバイダにより、システム内のあらゆるデータの標本を収集できます。たとえば、現在のスレッドの状態、CPU の状態、現在のマシンの命令などの標本を収集できます。


注 –

profile プロバイダのプローブからスレッド固有変数にアクセスすることはできません。そのようなプローブで特殊な識別子 self を使ってスレッド固有変数を参照しても、何も出力されません。


profile-n プローブ

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 スクリプトを短時間間実行します。このとき、 12345echo コマンドから返された 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 プローブ

tick-n プローブは、profile-n プローブと同じように、割り込みレベルが高く、固定の間隔で起動します。しかし、profile-n プローブのように各 CPU で起動するわけではありません。tick-n プローブは、毎回 1 個の CPU 上で起動します。実際の CPU は、時間の経過とともに変化します。profile-n プローブの場合と同じように、n はデフォルトでは秒当たりのレートですが、時間を表す接尾辞 (オプション) を付けることもできます。tick-n プローブには、定期的な出力、定期的なアクションの実行など、いくつかの用途があります。

引数

profile プローブの引数は、次の表のとおりです。

arg0

プローブが起動したときのカーネル内のプログラムカウンタ (PC)。プローブが起動したとき、カーネル内で現在のプロセスが実行されていなかった場合はゼロになります。 

arg1

プローブが起動したときのユーザーレベルのプログラムカウンタ (PC)。プローブが起動したとき、カーネル内で現在のプロセスが実行されていた場合はゼロになります。 

この説明からわかるように、arg0 がゼロ以外の値の場合 arg1 はゼロ、arg0 がゼロの場合 arg1 はゼロ以外になります。この特性を利用すると、arg0arg1 を使ってユーザーレベルとカーネルレベルを区別できます。以下に例を示します。

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 章安定性を参照してください。

要素 

名前の安定性 

データの安定性 

依存クラス 

プロバイダ 

発展中 

発展中 

共通

モジュール 

変更の可能性あり 

変更の可能性あり 

不明 

機能 

非公開 

非公開 

不明 

名前 

発展中 

発展中 

共通

引数 

発展中 

発展中 

共通