Toru Maesaka

Web addict and a hackaholic based in Tokyo

Archive for the ‘dtrace’ tag

メモ: DTraceを少し勉強してみた

without comments

なぜか今まで自分で調べるほど興味が向かなかったDTraceですが、最近よく耳にするようになった事もあり、少し勉強してみました。Mac OS X (10.5) から標準で使えるというのも大きかったですね。正直なところ、Solarisでしか動作しなかったら、DTraceに興味を示さなかったと思います。

ググってみたら、ITMediaなどで詳しく書かれている人がいるので、Yet another DTrace entryになってしまいますが、私の個人メモという事でお許しください。DTraceを調べてて思ったのが、Paul van den BogaardというSUNの人が書かれた、DTrace by Example: Solving a Real World Problemというドキュメントが凄く解り易かったです。

DTraceを簡素にいうと?

DTraceとはSUNがSolarisのために開発したダイナミックなトレーシング機能で、runtimeでシステムの動作をkernelレベルからトレースできるプロダクトです。Paulの資料ではフレームワークという表現がされていて、現在はSolarisの他にMac OS Xで使用する事が可能です。

DTraceを使うとシステム管理者や開発者などは手元のプログラムと、その更に下にあるOSに関する様々な情報を取得する事が可能になり、システムのプロファイリングやデバッグに役立ちます。ただ、DTraceと一言でいっても、様々なコンポーネントが絡んでいるので、気をつけないといけませんね:

  • OSのカーネル
  • D言語
  • dtraceコマンド
  • dtraceのバーチャルマシン
  • dtraceのプローブ
  • dtraceのプロバイダ
  • dtraceの各種ライブラリ

私が見たところ、DTraceの良いところは、ユーザ(システム管理者など)にとって興味のない情報を含んだ膨大なトレース結果が返されるのではなく、トレースする・返す情報を細かいレベルまで実際にD言語をつかって指定する事が可能な事でしょうか(例えばシステムコールの発行数・実行時間だけを返せとか)。つまりD言語をつかってカスタムなトレーサやプロファイラーを書く事ができるわけですね。

DTraceの流れ

D言語で記述されたトレーススクリプトは、dtraceコマンドによって実行します。スクリプトを受け取ったdtraceコマンドはOSのカーネルに組み込まれたdtraceのバーチャルマシンが理解できる中間形式に変換します(Javaでいうbytecodeっぽいですね)。あとはバーチャルマシンがユーザのスクリプトに記述されたロジックに基づいた集計を行ってくれます。

集計の流れ、そしてProbeとProvider

DTraceにはprobeという概念があり、probeとはカーネル内の計測ポイントを示します。Probeには様々な種類があり、それぞれ特定の条件下で有効になります(とあるシステムコールが発行されたなど)。したがって、D言語のスクリプトに特定のprobeを指定すると、そのprobeが有効になった際に報告される情報を収集できるとの事。

ちなみに私の使っているMacBook Pro (OS X 10.5.5, DTrace API version 1.2.2) のDarwin kernelに組み込まれているprobeの総数を見てみたところ:

# dtrace -l  

… (省略)

21652 plockstat4556 libSystem.B.dylib pthread_rwlock_wrlock$UNIX2003 rw-error
21653 plockstat4556 libSystem.B.dylib pthread_rwlock_unlock rw-release
21654 plockstat4556 libSystem.B.dylib pthread_rwlock_unlock$UNIX2003 rw-release

2万個以上ものProbeが発見されました。けっこうな数ですね〜。実際はオン・ザ・フライでprobeを生成するproviderが存在するので、probeはもっとあるらしいです。

SUN KKのDTraceドキュメント(日本語)によると、Probeが有効になると以下の情報が取得可能との事です:

  • 関数に渡されたすべての引数
  • カーネル内のすべての大域変数
  • 関数が呼び出された日時を示すタイムスタンプ
  • 関数を呼び出したコードセクションを示すスタックトレース
  • 関数が呼び出されたとき実行中だったプロセス
  • 関数を呼び出したスレッド

また、カーネル内でProbeを実際に有効にするカーネルモジュールをProviderと呼びます。Providerには色々な種類があって、特定のプロバイダに関連するprobeは、そのProviderにグルーピングされる様です。

ググってみたらProviderのリスト・種類の説明はDTraceのwikiとSolaris Dynamic Tracing Guideに載っていました:

http://wikis.sun.com/display/DTrace/Providers
http://docs.sun.com/app/docs/doc/817-6223(チャプター17から32まで)

D言語の書き方

私自身が人に教えれるほどD言語を把握していない事と、仕様を書くとブログエントリーの域を超えてしまうので、控えさせて頂きますが、DTraceユーザガイドの第3章に基本的な説明が記載されています。

楽な逃げ道を紹介すると、自分で頑張ってスクリプトをガリガリ書かなくても、DTraceToolKitという200種類以上もの充実したスクリプト集があります(存在を教えてくれたkiyotakaさんに感謝)。OS Xだと動かないスクリプトも結構あるみたいですが、私が試してみたメモリ関連のスクリプトは大丈夫っぽいです。

DTraceをMac OS Xで使ってみる(ワンライナー)

トリッキーな検査でなければ、スクリプトファイルを作成しなくても端末上でdtraceを試す事が可能です。

例えばプロセスがファイルを開いたら即座に報告する:

$ sudo dtrace -n 'syscall::open*:entry { printf("%s %s", execname, copyinstr(arg0)); }'

read(2)を呼んだプロセスを即座に報告する:

$ sudo dtrace -n 'syscall::read:entry { printf("%s", execname); }'
 
// OUTPUT:
// CPU     ID                FUNCTION:NAME
// 1       17602             read:entry mDNSResponder
// 1       17602             read:entry mDNSResponder
// 1       17602             read:entry EchoPod
// 1       17602             read:entry EchoPod

-p オプションでトレース対象を特定のプロセスに絞る (例, pid=6455):

$ sudo dtrace -p 6455 -n 'syscall::read:entry { printf("%s", execname); }'

など、ご覧の通りD言語を少し学ぶとPerlのワンライナー感覚で色々と遊べます。

余談

memcached-1.2.6には、ほぼ全てのコマンドに対しdtrace probeが組み込まれており、configure時に--enable-dtraceを指定するとprobeを適応する事ができるのです。つまり、memcachedに特化したtop(1)的なプログラムを数行で書けてしまうのです。

が、、現状だとOS Xの実装がSolarisと違うため、OS Xだとビルドに失敗してしまいます(dtraceの-Gオプションを認識しない)。この問題はSUNの技術者が絶賛対応中なので、1.3シリーズにはOS Xでビルドできるようになると期待していて、今後はmemcachedを修行相手にしてdtraceの知識や腕を磨きたいな〜、と思っています。

Written by tmaesaka

October 5th, 2008 at 11:57 pm

Posted in japanese

Tagged with