第102回カーネル読書会でDTraceの話を聴いた
第102回カーネル読書会に参加してきました。今回のお第は、OSやアプリケーションの実行をトレースする機構「DTrace」。その概要や、MySQLを対象として使う例について話を聴きました。
LinuxではDTraceはまだ開発中で、似たような機構としてSystemTapがあります。会場にはSystemTap開発チームの人も来ていて、その話なども出ました。ちなみにSystemTapではテトリスが実装されていて、なんでもキー操作をシステムコールのフックで検出するという無茶な(笑)ことをしているそうです。
以下、メモです。
DTrace Overview(加藤久慶)
まず、楽天の加藤さんがDTraceの概要を紹介しました。DTraceはSolaris 10からデフォルトで採用されたトレース機構で、いまはMac OS XやFreeBSDにも移植されているそうです。なお、Linux版は開発されているところ、とのことでした。
加藤さんはDTraceについて「デバッグツールと思われがちだが、開発者にも便利なツール」と語り、実際にデモしてみせました。まず、「dtrace -l」コマンドを実行して約6万個のプローブ一覧を表示してみせました。
続いて「dstrace -n 'syscall::entry'」を実行してシステムコールの呼び出しをトレースしてみせました。デフォルトでは全プロセスが対象になるので、出力を見て対象プロセスを特定し、そこからさらに絞り込んでいく、というふうに追いかけていくそうです。
ほか、ZFSのファンクションを呼んだ回数をカーネルのスレッド単位で調べたり、CPUリソースを使っているものをプロファイリングしたりといった例を紹介しました。また、最後によく使うケースのワンライナーを紹介してまとめました。
DTraceでMySQLを斬る(奥野幹也)
奥野さんは、DTraceを使ってMySQLの動作を追いかけ、DBチューニングに役立てる方法を解説しました。なお、奥野さんはMySQLの中の人ですが、今回は個人としての発表だそうです。
まずMySQLの紹介として、「永久に不滅です」「ちゃんとしたデータベースです」というメッセージを掲げました。MySQLの構造としては、モノリシックカーネル、シングルプロセス・マルチスレッド、1セッション=1スレッド(コネクションスレッド)、ストレージエンジンAPIによる仮想化などが特徴として挙げられました。なお、ソースコードは100万行程度だそうです。
続いて、DTraceを紹介。対象プログラムに「プローブ」を動的に埋め込むことによってプロファイルする構造だそうです。プログラムの実行がプローブにかかると、プローブがfireしてDTraceに制御が移るようになっているとのこと。なお、プローブを埋め込む場所は、ふだんはNOPなどのオーバーヘッドのないものになっているという話でした。
DTraceの動作は、D言語(D Language)というスクリプト言語で記述します。ちょっとD言語(D Programming Language)とまぎらわしい名前ですが。1つのプローブの記述(節)は、以下のような形式になります。
プローブ記述子 /述語/ { アクション }
プローブ記述子の書式は、「プロバイダ名:モジュル名:関数名:プローブ名」のようになります。fireする条件(および述語による条件指定)と、そのときの動作を対にする形式で、ちょっとawkっぽいですね。なお、C++は関数名がmangleされているのでワイルドカードを使うと便利、というTipsも紹介されました。
アクションはセミコロン区切りで指定。省略すると、fireしたというメッセージが出力されるそうです。普通はprintfやtrace(スタックトレース形式出力)で出力するほか、投機バッファというメモリ領域に出力することもできるそうです。
また、変数として、組み込み変数、外部変数(カーネル用)、節固有変数(ローカル変数みたいなもの)、スレッドローカル変数、スカラー変数(あまり使われない)が紹介されました。組み込み変数でプローブへの引数がとれますが、引数はユーザー空間、DTraceはカーネル空間なので、copyinstr()でコピーする必要がある、という注意も紹介されました。
最近のMySQLでは、公式ソースの中にD言語によるプローブ定義が含まれているそうです。ビルド時にCのプリプロセッサマクロによりプラットフォームが識別され、Linuxでは何も埋め込まれないようになっているとのことでした。
ここで、デモ。2つのターミナルを表示し、片方でDTraceを、もう片方でMySQLクライアントを動かしてみせました。紹介された例は以下のとおり。
- クエリーのSQLをダンプ
- メモリ不足の原因を調べる:述語に「/ errno == NOMEM /」を指定
- エラーメッセージを追跡:プローブとして「mysql$target:*my_errror:entry」を指定
- キーキャッシュのヒット率:query-cache-hitとquery-cache-missのプローブから
- 1000行以上のFile Sortを検出:filesort-startとfilesort-doneのプローブから
- テーブルごとのソート統計:exit時に合計を出力
- ソート中断の原因を調査:filesort-doneの述語として「/ self->q && arg0 /」を指定。arg0が0以外だとエラーになる
また、DTraceを使った便利なユーティリティ群「DTrace Toolkit」を紹介しました。DTraceを知らなくても使えるようになっていて、Mac OS Xではデフォルトでインストールされているそうです。シグナルが送られたときに反応する「kill.d」とか便利そうですね。
最後に、技術評論社から近日刊という書籍「MySQLエキスパートトラブルシューティングガイド(仮)」を紹介して締めました。
コメント
コメントの投稿
トラックバック
https://emasaka.blog.fc2.com/tb.php/734-d01b828f