Solaris 動的トレースガイド

以下は、mpstat(1M) の出力例です。


CPU minf mjf xcal  intr ithr  csw icsw migr smtx  srw syscl  usr sys  wt idl
 12   90  22 5760   422  299  435   26   71  116   11  1372    5  19  17  60
 13   46  18 4585   193  162  431   25   69  117   12  1039    3  17  14  66
 14   33  13 3186   405  381  397   21   58  105   10   770    2  17  11  70
 15   34  19 4769   109   78  417   23   57  115   13   962    3  14  14  69
 16   74  16 4421   437  406  448   29   77  111    8  1020    4  23  14  59
 17   51  15 4493   139  110  378   23   62  109    9   928    4  18  14  65
 18   41  14 4204   494  468  360   23   56  102    9   849    4  17  12  68
 19   37  14 4229   115   87  363   22   50  106   10   845    3  15  14  67
 20   78  17 5170   200  169  456   26   69  108    9  1119    5  21  25  49
 21   53  16 4817    78   51  394   22   56  106    9   978    4  17  22  57
 22   32  13 3474   486  463  347   22   48  106    9   769    3  17  17  63
 23   43  15 4572    59   34  361   21   46  102   10   947    4  15  22  59

この出力をよく見ると、システムが比較的アイドル状態にあるのに xcal フィールドの値が大きすぎることがわかります。mpstat は、xcal フィールドの値を決めるとき、sys カーネル統計情報の xcalls フィールドを調べます。したがって、次の例のように xcalls sysinfo プローブを有効にすれば、この異常について簡単に調べることができます。


# dtrace -n xcalls'{@[execname] = count()}'
dtrace: description 'xcalls' matched 4 probes
^C
  dtterm                                                            1
  nsrd                                                              1
  in.mpathd                                                         2
  top                                                               3
  lockd                                                             4
  java_vm                                                          10
  ksh                                                              19
  iCald.pl6+RPATH                                                  28
  nwadmin                                                          30
  fsflush                                                          34
  nsrindexd                                                        45
  in.rlogind                                                       56
  in.routed                                                       100
  dtrace                                                          153
  rpc.rstatd                                                      246
  imapd                                                           377
  sched                                                           431
  nfsd                                                           1227
  find                                                           3767

この出力から、クロスコールのソースをどこで探せばよいかがわかります。ほとんどのクロスコールは、find(1) プロセス数個に影響を受けています。問題をもっと詳しく調べるには、次の D スクリプトを使用します。

syscall:::entry
/execname == "find"/
{
	self->syscall = probefunc;
	self->insys = 1;
}

sysinfo:::xcalls
/execname == "find"/
{
	@[self->insys ? self->syscall : "<none>"] = count();
}

syscall:::return
/self->insys/
{
	self->insys = 0;
	self->syscall = NULL;
}

このスクリプトでは、syscall プロバイダを使って、find からのクロスコールがどのシステムコールに起因するか調べます。ページフォルトに起因するクロスコールなど、システムコールに起因しないクロスコールも存在します。この場合は <none> と出力されます。このスクリプトを実行すると、次のような出力が得られます。


# dtrace -s ./find.d
 dtrace: script './find.d' matched 444 probes
^C
  <none>                                                            2
  lstat64                                                        2433
  getdents64                                                    14873

find によるクロスコールの大部分が、システムコール getdents(2) によって行われています。以降の作業は、調べたい内容に応じて異なります。たとえば、find プロセスが getdents を呼び出している理由を調べたい場合は、find がクロスコールを引き起こしたときに ustack() を集積するような D スクリプトを作成するとよいでしょう。getdents の呼び出しがクロスコールを引き起こす理由を調べたい場合は、find がクロスコールを引き起こしたときに stack() を集積するような D スクリプトを作成するとよいでしょう。次の作業が何であっても、xcalls プローブを利用することで、異常な監視結果が出力された原因を簡単に突き止めることができます。