C/C++プログラマのためのDTrace入門

第4回 前提条件の記述

この記事を読むのに必要な時間:およそ 4 分

これまで説明してきたDスクリプトでは,モジュール名や関数名といった単位で採取対象を特定していました。

今回は,もっと複雑な採取対象の絞り込みを可能とする,前提条件の記述方法について説明したいと思います。

特定関数の呼び出し契機での絞り込み

本連載でこれまで例示してきたDスクリプトは,特定の関数から引数や戻り値を採取する一部の例外を除いては,基本的に全ての関数フローを採取するものでした。

しかし,必ずしも全ての関数フローの採取が必要なケースばかりではありません。むしろ全ての関数フローを採取した場合,以下のようなデメリットが生じます。

  • 採取結果の中から調査対象を特定するのが難しくなる
  • 採取結果の記録に必要なディスク領域が増加する

このようなデメリットを無くすためには,採取範囲の絞り込みが必要です。

たとえば,リスト1のプログラムshow_nestingを想定してみましょう。

リスト1 関数の入れ子show_nesting

void f1(){ }

void f2(){ f1(); }

void f3(){ f2(); }

void f4(){ f3(); }

int
main(int argc,
     const char* argv[])
{
    f4();
    return 0;
}

これまで使用してきた関数フロー採取用のDスクリプトを使用した場合,リスト2のように全ての関数フローが採取されます。

リスト2 全関数フローの採取結果

CPU FUNCTION
  0  -> _start
  0    -> __fsr
  0    <- __fsr
  0    -> main
  0      -> f4
  0        -> f3
  0          -> f2
  0            -> f1
  0            <- f1
  0          <- f2
  0        <- f3
  0      <- f4
  0   <- main

ここで,このプログラムの実行における最も重要な処理が,関数f3()呼び出しから先の処理である,と仮定しましょう。

この前提における関数フローの採取は,関数f3()が呼ばれた時点から開始し,関数f3()から復帰した時点で停止する,というのが理想的と言えるでしょう。

このような採取範囲の絞り込みを行うには,リスト3のようなDスクリプトを使用します。

リスト3 採取範囲の絞り込みwatch_focused.d

pid$target:show_nesting:f3:entry
{
    self->traced = 1;
}

pid$target:show_nesting::entry,
pid$target:show_nesting::return
/self->traced/
{
}

pid$target:show_nesting:f3:return
{
    self->traced = 0;
}

それでは関数フローを採取してみましょう。

図1 caption

$ dtrace -F \
         -s watch_focused.d \
         -c ./show_nesting
dtrace: script 'watch_focused.d' matched 15 probes
CPU FUNCTION
  0  -> f3
  0    -> f2
  0      -> f1
  0      <- f1
  0    <- f2
  0  <- f3
dtrace: pid 12820 has exited
$

リスト2と比較してみればおわかりのように,関数f3()呼び出し以後の関数フローのみが,採取対象となっています。

著者プロフィール

藤原克則(ふじわらかつのり)

Mercurial三昧の日々が嵩じて, いつの間にやら『入門Mercurial Linux/Windows対応』を上梓。凝り性なのが災いして,年がら年中アップアップな一介の実装屋。最近は仕事の縁が元で,OpenSolarisに入れ込む毎日。

コメント

コメントの記入