DTrace ユーザーガイド

sysinfo プロバイダを使ってパフォーマンスの問題を検査する

sysinfo プロバイダは、sys カーネル統計情報のプローブを使用できるようにします。これらの統計情報は、mpstat などのシステム監視ユーティリティーの入力となります。sysinfo プロバイダのプローブは、kstat コマンドで表示される sys の値が増分される直前に起動します。次に、sysinfo プロバイダが提供するプローブを一覧します。

bawrite

バッファーからデバイスへの非同期書き出しが行われる直前に起動するプローブ。

bread

デバイスからのバッファーの物理読み取りが行われたときに起動するプローブ。bread は、デバイスがバッファーを要求したあと、処理の完了が保留される前に起動します。

bwrite

バッファーからデバイスへの書き出しが行われる直前に起動するプローブ。書き出しは、同期書き出し、非同期書き出しの両方を含みます。

cpu_ticks_idle

定期的なシステムクロックにより、「CPU がアイドル状態である」という判断が下されたとき起動するプローブ。このプローブは、システムクロックのコンテキストで起動します。したがって、システムクロックを実行している CPU 上で起動することになります。cpu_t の引数 (arg2) は、アイドル状態だと判断された CPU を表します。

cpu_ticks_kernel

定期的なシステムクロックにより、「CPU がカーネルで実行中である」という判断が下されたとき起動するプローブ。このプローブは、システムクロックのコンテキストで起動します。したがって、システムクロックを実行している CPU 上で起動することになります。cpu_t の引数 (arg2) は、カーネルで実行中であると判断された CPU を表します。

cpu_ticks_user

定期的なシステムクロックにより、「CPU がユーザーモードで実行中である」という判断が下されたとき起動するプローブ。このプローブは、システムクロックのコンテキストで起動します。したがって、システムクロックを実行している CPU 上で起動することになります。cpu_t の引数 (arg2) は、ユーザーモードで実行中であると判断された CPU を表します。

cpu_ticks_wait

定期的なシステムクロックにより、「CPU 上に入出力待ちのスレッドがあるほかはアイドル状態である」という判断が下されたとき起動するプローブ。このプローブは、システムクロックのコンテキストで起動します。したがって、システムクロックを実行している CPU 上で起動することになります。cpu_t の引数 (arg2) は、入出力待ち状態だと判断された CPU を表します。

idlethread

CPU がアイドルループに入ったときに起動するプローブ。

intrblk

割り込みスレッドがブロックされたときに起動するプローブ。

inv_swtch

実行中のスレッドが CPU の解放を強制されたとき起動するプローブ。

lread

デバイスからのバッファーの論理読み取りが行われたときに起動するプローブ。

lwrite

バッファーからデバイスへの論理書き込みが行われたときに起動するプローブ。

modload

カーネルモジュールがロードされたときに起動するプローブ。

modunload

カーネルモジュールがアンロードされたときに起動するプローブ。

msg

msgsnd(2) または msgrcv(2) システムコールが発行されたあと、メッセージキュー操作が行われる前に起動するプローブ。

mutex_adenters

所有されている適応型ロックの獲得が試みられたときに起動するプローブ。このプローブが起動するときは、lockstat プロバイダの adaptive-block プローブ、または adaptive-spin プローブも起動します。

namei

ファイルシステム内で名前の検索が試みられたときに起動するプローブ。

nthreads

スレッドが作成されたときに起動するプローブ。

phread

生の入出力読み取りが行われる直前に起動するプローブ。

phwrite

生の入出力書き込みが行われる直前に起動するプローブ。

procovf

システムのプロセステーブルのエントリがなくなったため新しいプロセスを作成できないときに起動するプローブ。

pswitch

CPU が実行スレッドを切り替えたときに起動するプローブ。

readch

正常に読み取りが行われたあと、この読み取りの実行スレッドに制御が移る前に起動するプローブ。読み取りは、read(2)readv(2)、または pread(2) システムコールによって行われます。arg0 には、正常に読み取られたバイト数が格納されます。

rw_rdfails

書き込み側が読み取りロックまたは書き込みロックを保持している場合、または必要としている場合に、読み取りロックが試みられたとき起動するプローブ。このプローブが起動するときは、lockstat プロバイダの rw-block プローブも起動します。

rw_wrfails

読み取り側か別の書き込み側が読み取りロックまたは書き込みロックを保持している場合に、書き込みロックが試みられたとき起動するプローブ。このプローブが起動するときは、lockstat プロバイダの rw-block プローブも起動します。

sema

システムコール semop(2) が発行されたあと、セマフォー操作が行われる前に起動するプローブ。

sysexec

システムコール exec(2) が発行されたときに起動するプローブ。

sysfork

システムコール fork(2) が発行されたときに起動するプローブ。

sysread

システムコール readreadv、または pread が発行されたときに起動するプローブ。

sysvfork

システムコール vfork(2) が発行されたときに起動するプローブ。

syswrite

システムコール write(2)writev(2)、または pwrite(2) が発行されたときに起動するプローブ。

trap

プロセッサトラップが発生したときに起動するプローブ。ただし、一部のプロセッサ、特に UltraSPARC 系プロセッサでは、一部の軽量トラップを処理するときにこのプローブを起動しないことがあります。

ufsdirblk

UFS ファイルシステムによるディレクトリブロックの読み取りが行われたときに起動するプローブ。UFS については、ufs(7FS) のマニュアルページを参照してください。

ufsiget

i ノードの取得時に起動するプローブ。UFS については、ufs(7FS) のマニュアルページを参照してください。

ufsinopage

データページが関連付けられていないコア内の i ノードの再利用が可能になったあと起動するプローブ。UFS については、ufs(7FS) のマニュアルページを参照してください。

ufsipage

データページが関連付けられたコア内の i ノードの再利用が可能になったあと起動するプローブ。このプローブは、関連付けられたデータページがディスクにフラッシュされたあとで起動します。UFS については、ufs(7FS) のマニュアルページを参照してください。

wait_ticks_io

定期的なシステムクロックにより、「CPU 上に入出力待ちのスレッドがあるほかはアイドル状態である」という判断が下されたとき起動するプローブ。このプローブは、システムクロックのコンテキストで起動します。したがって、システムクロックを実行している CPU 上で起動することになります。cpu_t の引数 (arg2) は、入出力待ち状態だと判断された CPU を表します。wait_ticks_iocpu_ticks_wait には、意味上の違いはありません。wait_ticks_io は、履歴上の理由で提供されているだけです。

writech

正常に書き込みが行われたあと、この書き込みの実行スレッドに制御が移る前に起動するプローブ。書き込みに使用されるシステムコールは、 writewritevpwrite のいずれかです。arg0 には、正常に書き込まれたバイト数が格納されます。

xcalls

クロスコールが行われる直前に起動するプローブ。クロスコールは、一方の CPU から、別の CPU によるすばやい処理を要求するオペレーティングシステム機構です。


例 4–1 sysinfo プローブで quantize 集積関数を使用する

quantize 集積関数は、引数の二乗度数分布を示す棒グラフを表示します。次の例では、quantize 関数を使って、10 秒間にシステム上の全プロセスで実行される read 呼び出しのサイズを確認します。sysinfo プローブの引数 arg0 には、統計情報の増分の分量を指定します。ほとんどの sysinfo プローブでは、この値は 1 です。ただし、readch プローブと writech プローブは例外です。これらのプローブでは、引数 arg0 に、実際に読み取られるバイト数、または実際に書き込まれるバイト数を指定します。


# cat -n read.d
   1  #!/usr/sbin/dtrace -s
   2  sysinfo:::readch
   3  {
   4     @[execname] = quantize(arg0);
   5  }
   6
   7  tick-10sec
   8  {
   9     exit(0);
  10  }

# dtrace -s read.d
dtrace: script 'read.d' matched 5 probes
CPU        ID                    FUNCTION:NAME
  0     36754                      :tick-10sec

  bash
         value  ---------- Distribution ---------- count
             0 |                                   0
             1 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 13
             2 |                                   0

  file
         value  ---------- Distribution ---------- count
            -1 |                                   0
             0 |                                   2
             1 |                                   0
             2 |                                   0
             4 |                                   6
             8 |                                   0
            16 |                                   0
            32 |                                   6
            64 |                                   6
           128 |@@                                 16
           256 |@@@@                               30
           512 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@      199
          1024 |                                   0
          2048 |                                   0
          4096 |                                   1
          8192 |                                   1
         16384 |                                   0

  grep
         value  ---------- Distribution ---------- count
            -1 |                                   0
             0 |@@@@@@@@@@@@@@@@@@@                99
             1 |                                   0
             2 |                                   0
             4 |                                   0
             8 |                                   0
            16 |                                   0
            32 |                                   0
            64 |                                   0
           128 |                                   1
           256 |@@@@                               25
           512 |@@@@                               23
          1024 |@@@@                               24
          2048 |@@@@                               22
          4096 |                                   4
          8192 |                                   3
         16384 |                                   0


例 4–2 クロスコールのソースを確認する

次に、mpstat(1M) コマンドの出力例を示します。


CPU minf mjf xcal  intr ithr  csw icsw migr smtx  srw syscl  usr sys  wt idl
  0 2189   0 1302    14    1  215   12   54   28    0 12995   13  14   0  73
  1 3385   0 1137   218  104  195   13   58   33    0 14486   19  15   0  66
  2 1918   0 1039    12    1  226   15   49   22    0 13251   13  12   0  75
  3 2430   0 1284   220  113  201   10   50   26    0 13926   10  15   0  75

xcal 欄と syscl 欄の値が異常に大きいため、システムパフォーマンスが浪費されている可能性があります。システムは比較的アイドル状態にあり、入出力の待ち時間が異常に長くなっているわけでもありません。xcal 欄の数値は sys kstat の xcalls フィールドから読み取られたものであり、秒単位で表されています。クロスコールを行う実行可能ファイルを確認するには、次のような dtrace コマンドを入力します。


# dtrace -n 'xcalls {@[execname] = count()}'
dtrace: description 'xcalls ' matched 3 probes
^C
  find                                                   2
  cut                                                    2
  snmpd                                                  2
  mpstat                                                22
  sendmail                                             101
  grep                                                 123
  bash                                                 175
  dtrace                                               435
  sched                                                784
  xargs                                              22308
  file                                               89889
#

出力結果から、大量のクロスコールが file(1)xargs(1) のプロセスによって行われていることがわかります。これらのプロセスを確認するには、pgrep(1) コマンドと ptree(1) を使用します。


# pgrep xargs
15973
# ptree 15973
204   /usr/sbin/inetd -s
  5650  in.telnetd
    5653  -sh
      5657  bash
        15970 /bin/sh ./findtxt configuration
          15971 cut -f1 -d:
            15973 xargs file
              16686 file /usr/bin/tbl /usr/bin/troff /usr/bin/ul /usr/bin/vgrind /usr/bin/catman

出力結果から、xargs コマンドと file コマンドがカスタムユーザーシェルスクリプトの一部であることがわかります。このスクリプトを検出するには、次のコマンドを実行します。


# find / -name findtxt
/usrs1/james/findtxt
# cat /usrs1/james/findtxt
#!/bin/sh
find / -type f | xargs file | grep text | cut -f1 -d: > /tmp/findtxt$$
cat /tmp/findtxt$$ | xargs grep $1
rm /tmp/findtxt$$
#

このスクリプトは、多くのプロセスを同時に実行しています。パイプ経由で大量のプロセス間通信が行われています。パイプ数が多いと、スクリプトリソースが集中的に使用されます。このスクリプトは、システム上のすべてのテキストファイルの検出を試みたあと、各ファイルから特定のテキストを検索します。