Oprofileでプロファイリングしよう

カーネルモジュールのボトルネックを測定したい。こんなことよくあります。Oprofileは、そんな要求に応えられる、非常にいけてるプロファイラです。最近のLinuxカーネルであれば、再コンパイルなしにプロファイリングすることができます:D。
本記事では「Ubuntu上でカーネルモジュールのプロファイリング」が行えることを目標とします。
もちろんユーザプロセスでもプロファイリング可能ですが、これについてはBinary HacksやWeb上にたくさん載っているので、そちらを参照してください。

まずはインストール

apt経由でOprofileをインストールしましょう。

sudo aptitude install oprofile

生のvmlinuxを用意する

カーネルモジュールのプロファイリングを行うためには、「生のvmlinux」が必要です。
一方、Ubuntuインストーラによってインストールされるvmlinuz-`uname -r`は、ブート時のカーネル解凍ルーチンと圧縮カーネルがくっついているので、bunzipでは解凍できません。*1 *2

Ubuntu*3の場合、このイメージはパッケージ化されているので、aptでインストールすることができます。

# `は Backquotation
sudo aptitude install linux-image-debug-`uname -r`

Oprofileの初期化

Oprofileカーネルモジュールを読み込み、初期化処理を行います。

sudo modprobe oprofile
# 初期化処理
sudo opcontrol --init
# vmlinuxのパスを指定
sudo opcontrol --vmlinux=/boot/vmlinux-`uname -r`

これで準備は整いました。

Let's profile vmlinux!

まずはカーネル全体のプロファイリングをしてみましょう!以下のコマンドで開始できます。

sudo opcontrol --start # profiling デーモンの開始
sleep 30 #30秒でどんな処理が行われているのかを見る。
sudo opcontrol --stop
sudo opcontrol --dump # プロファイルした値を読める値にダンプ
sudo opreport # プロファイルの結果を表示

Let's profile kernel module!

つぎに、カーネルモジュールのプロファイリングです。カーネルモジュールをhello.koとしてみましょう。

sudo insmod ./hello.ko
--
sudo opcontrol --start
sleep 30 #30秒でどんな処理が行われているのかを見る。
sudo opcontrol --stop
sudo opcontrol --dump # プロファイルした値を読める値にダンプ
sudo opreport # プロファイルの結果を表示
--
sudo opreport -p kmod-dir-path # プロファイルの結果を表示。

勘の良い方は気づかれたかもしれませんが、実はプロファイルング自体の処理はカーネル全体のプロファイリングと変わりません。このことから、opreportを呼ぶときにカーネルモジュールのシンボル情報を与えて、人間に読めるようにしているということが予測できます。

例を挟みたい感じ。あとで更新するかも。

バッドノウハウ

Oprofile Q&Aにある通り、vmwareと一緒だと動きません。
CPUによってとれる値が変わるようです。i686系だと全機能を使えるのだとか。

*1:かといって、生のvmlinuxから起動する必要はありません。何故なら、Oprofileが使用するのはELFバイナリの中に入っているシンボル情報だけだからです。

*2:生のvmlinuxから起動するのは不可能です。生のvmlinuxは単なるELFバイナリだから:D 確かMultiboot specificationで策定されているMagicはsetup.oの方にあるので、vmlinux単体だと結局起動できないはずです。

*3:ちょっと見た感じだとCestOSもデバッグ用のカーネルイメージをパッケージで配布してるっぽい。