NetBSD ドキュメンテーション: カーネルプロファイリング HOWTO
この文章にはどのようにカーネルプロファイリングが動作し、
どう使うのかが書かれています。このドキュメントは Matthias Drochner
<drochner@zel459.zel.kfa-juelich.de>
の筆によります。
カーネルプロファイリング
カーネルプロファイリング
どのように動作するのか (トップ)
プロファイル済みのコードの振る舞いに関する、 2種類のデータが個別に記録されます: 全関数の呼び出し頻度 (呼び出しグラフプロファイリング) と各関数の処理にかかった時間です。 これらは、適当にサンプルされた時に関数内にあるプログラムカウンターの確率によって概算され、 その確率は、調べている関数が実行中に起こる、 プロファイリングタイマーの割り込み率によって逆に概算されます。 gprof(1) というユーティリティーを使って、データを解釈します。 しかし、二つのデータの相関性がないため、いくつか制限が出てきます。 これは、manページのBUGSの章に書かれています。
カーネルのプロファイリングとユーザープログラムのプロファイリングは、 よく似ています; プロファイリングデータを処理する方法と、 コントロールする方法が若干違う程度です。
カーネルプロファイリングに関係するデータは、
グローバル構造体の _gmonparam
内にあります。
この構造体は、(
kern/subr_prof.c
中の) kmstartup()
により、
システムが初期化する際に初期化されます。
ユーザーレベルのコントロールプログラムである kgmon(8) は、
コントロールとデータアクセスのために
sysctl(3) を呼び出し、
一部 kvm(3) アクセスを呼び出しています
(動作しているカーネルがプロファイルされる標準的な場合もです!) 。
呼び出しグラフの記録 (トップ)
プロファイリングのフラグ (-pg
) により、
コンパイラーは関数のエントリーごとに mcount()
を呼び出します。
これは、マシン独自の橋渡しによって、
_mcount(frompc,selfpc)
へ送られます。
_mcount(frompc,selfpc)
は
sys/lib/libkern/mcount.c
で実装されます。
frompc
は関数を呼び出すアドレスで、 selfpc
は呼ばれる関数自体のアドレスです。
プロファイル中に遭遇する全ての (frompc
, selfpc
)
用に、 struct tostruct
は _gmonparam.tos
が示す配列から割り当てられます。
エントリーは最初に使用する順番で、
始めから終わりまで単純に割り当てられます。 kmstartup()
内のあるマジックによって、
カーネルのテキストサイズから配列のサイズが決められます --
一種の"経験則" のようです。
struct tostruct
のエントリーは、ヒストグラムカウンターと一緒に、呼ばれた関数
(selfpc
)
のアドレスを持っています。
同じ呼び出しアドレスにあるエントリーは、リンクした一覧を形成します。
一覧のヘッド (つまり、特定の呼び出しアドレスに属する
_gmonparam.tos
配列内の最初のエントリーの見出し) は、
_gmonparam.froms
という二つ目のデータ配列にあります。この
_gmonparam.froms
は、
ある値によって分割された呼び出しアドレス
(frompc
)
により、見出しを付けられます (ある値は、コード内の二つの呼び出しの最短距離
より長くなることはありません - sys/sys/gmon.h
にあるコメントを見てください) 。
標準的な関数呼び出しには、それぞれの
frompc
に対して
selfpc
がひとつしかないことに注意してください。
その結果、典型的な一覧が一つのメンバーのみで構成されるようになります。
統計的なプロファイリング (トップ)
プロファイリングが始まると、プロファイリングタイマーの割り込みが
セットされ、 statclock()
を呼び出します (
sys/kern/kern_clock.c
を参照してください) 。
プロファイリングタイマーは、関数への干渉がシステムのクロックと
同期して動かなくならないように、通常のシステムクロックから独立した
タイマーであるべきです。 statclock()
はユーザープログラムでも、
カーネルプロファイリングでも使われます。
ある値で再分割されていれば、
割り込み時にプログラムカウンターは見出しとして使われて、
ヒストグラムの _gmonparam.kcount
に記録され、該当するセルの値が増えます。
使い方 (トップ)
- プロファイリングカーネルを構築し、ブートします。
これには、
-p
フラグを用いて config(8) します。 用いなければ、特別なことはありません。プロファイリングカーネルは 以下のようなメッセージを自動設定後、ルートファイルシステムが マウントされる前に出力します。Profiling kernel, textsize=1611256 [f0100000..f02895f8]
-
/netbsd
が現在動作しているカーネルであるか 確認してください。もし違えば、下の kgmon(8) の呼び出しで、-N
オプションを使ってください。 -
kgmon -b
でプロファイリングを開始します。 - いくつかアプリケーションを起動して、システムの中でも調べたい部分に 負担をかけます。
-
kgmon -h
でプロファイリングを止めます。 -
kgmon -p
を起動して、収集したデータをgmon.out
というファイルに書き込みます。 - 他のものを計測する前に、
kgmon -r
でカーネル内のプロファイリングデータのバッファーをリセットします。 -
gmon.out
から人間が判読できる解釈を入手するため、 以下のコマンドを実行します。% gprof /netbsd gmon.out > gprof.txt
- データの解釈をします。
Back to NetBSD ドキュメンテーション: カーネル