OProfile は動的なプログラム分析のためのプロファイラです。動作中のプログラムに対する振る舞いを調査して、情報を収集します。この情報は表示することができるため、さらなる最適化のためのヒントとすることができます。
OProfile を使用するにあたって、再コンパイルやラッパーライブラリの使用は必要ありません。カーネルに適用すべきパッチもありません。負荷とサンプリング周期にもよりますが、アプリケーションをプロファイルしている間、少しだけオーバーヘッドが現れます。
OProfile はカーネルドライバとデーモンから構成され、データを収集することができます。また、多くのプロセッサに搭載されている、ハードウエア側のパフォーマンスカウンタを利用して測定を行います。 OProfile はカーネルやカーネルモジュール、カーネルの割り込みハンドラやシステムの共有ライブラリ、その他のアプリケーションなど、全てのコードをプロファイルすることができます。
新しいプロセッサであれば、パフォーマンスカウンタと呼ばれるハードウエアを介してプロファイルを行うことができます。プロセッサ側の使用にも依存しますが、様々なカウンタが用意され、それらはイベントの発生回数をカウントするようプログラムすることができます。また、それぞれのカウンタには、どれくらいの間隔でサンプルを採取したのかを示す値が用意されています。値が低いほど多く使用されたことになります。
なお、事後の作業で全ての情報を収集し、インストラクションアドレスは関数名に変換されます。
OProfile を使用するには oprofile
パッケージをインストールします。
なお、プロファイル対象のアプリケーションに対応する *-debuginfo
パッケージをインストールしておくことをお勧めします。カーネルをプロファイルする場合は、カーネルの debuginfo
パッケージもインストールしてください。
OProfile にはプロファイルを行ったりそのデータを収集したりする目的で、いくつかのユーティリティが提供されています。下記の一覧には、本章で使用するプログラムの概要を説明しています:
opannotate
注釈付きソースやアセンブリリストとプロファイル情報を出力するためのユーティリティです。注釈付きのレポートは addr2line
と組み合わせて使用され、ホットスポットが存在しうるソースコードのファイルとその行を識別することができます。詳しくは man addr2line
をお読みください。
operf
プロファイラツールです。プロファイリングを停止すると、既定では カレントディレクトリ/oprofile_data/samples/current
にデータを保存しますので、ここから opreport
コマンドなどで処理できるようになります。
ophelp
利用可能なイベントと、その短い説明を一覧表示します。
opimport
異なるバイナリ形式で書かれたサンプルデータベースファイルを、ネイティブ形式に変換します。
opreport
プロファイルしたデータからレポートを生成します。
OProfile を使用することで、カーネルとアプリケーションの両方をプロファイルすることができます。カーネルをプロファイルする場合は、 OProfile に対して vmlinuz*
ファイルの検索先を指定するため、 --vmlinux
オプションで場所を指定します (一般に /boot
です) 。カーネルモジュールをプロファイルする必要がある場合も、 OProfile は自動的にそれを行います。ただし、念のため https://oprofile.sourceforge.net/doc/kernel-profiling.html (英語) をお読みになることをお勧めします。
アプリケーションをプロファイルする際、ほとんどの場合においてカーネルのプロファイルは不要になります。そのため、 --no-vmlinux
オプションを指定して情報量を減らしておくことをお勧めします。
アプリケーション COMMAND に対するプロファイルを行うため、デーモンを起動してデータを収集し、デーモンを停止させたあとレポートを作成するまでの手順を説明します。
シェルを開いて root
になります。
Linux カーネルを含めてプロファイルするかどうかを判断し、それぞれを行います:
Linux カーネルを利用したプロファイル: operf
は無圧縮のイメージのみを扱うことができますので、下記のようにコマンドを入力して実行します:
>
cp /boot/vmlinux-`uname -r`.gz /tmp>
gunzip /tmp/vmlinux*.gz>
operf--vmlinux=/tmp/vmlinux* COMMAND
Linux カーネルを利用しないプロファイル: 下記のようにコマンドを入力して実行します:
#
operf --no-vmlinux COMMAND
出力内に一方の関数から他方の関数を呼び出している様子を表示させたい場合は、 --callgraph
を指定して最大の 深さ を設定してください:
#
operf --no-vmlinux --callgraph
深さ COMMAND
operf
はデータを カレントディレクトリ/oprofile_data/samples/current
に書き込みます。 operf
コマンドが終了したら (もしくは Ctrl–C で停止させたら) 、oreport
を利用して解析を行うことができます:
#
opreport
Overflow stats not available
CPU: CPU with timer interrupt, speed 0 MHz (estimated)
Profiling through timer interrupt
TIMER:0|
samples| %|
------------------
84877 98.3226 no-vmlinux
...
イベントを設定するための一般的な手順は下記のとおりです:
まずは CPU-CLK_UNHALTED
と INST_RETIRED
の各イベントを利用して、最適化の可能性を探ります。
特定のイベントを利用してボトルネックを探ります。イベントの一覧を表示するには、 perf list
と入力して実行してください。
特定のイベントをプロファイルする必要がある場合は、まずお使いのプロセッサ側がそのイベントに対応しているかどうかを調べる必要があります。具体的には、 ophelp
コマンドを実行します (下記は Intel Core i5 CPU での出力例です):
#
ophelp
oprofile: available events for CPU type "Intel Architectural Perfmon" See Intel 64 and IA-32 Architectures Software Developer's Manual Volume 3B (Document 253669) Chapter 18 for architectural perfmon events This is a limited set of fallback events because oprofile does not know your CPU CPU_CLK_UNHALTED: (counter: all)) Clock cycles when not halted (min count: 6000) INST_RETIRED: (counter: all)) number of instructions retired (min count: 6000) LLC_MISSES: (counter: all)) Last level cache demand requests from this core that missed the LLC (min count: 6000) Unit masks (default 0x41) ---------- 0x41: No unit mask LLC_REFS: (counter: all)) Last level cache demand requests from this core (min count: 6000) Unit masks (default 0x4f) ---------- 0x4f: No unit mask BR_MISS_PRED_RETIRED: (counter: all)) number of mispredicted branches retired (precise) (min count: 500)
--event
オプションでパフォーマンスカウンタイベントを指定します。複数のオプションを指定してもかまいません。このオプションはイベント名 (ophelp
で表示される名前) とサンプリングレートを指定します。たとえば下記のようになります:
#
operf --events CPU_CLK_UNHALTED:100000
CPU_CLK_UNHALTED
に対するサンプリングレート設定についてサンプリングレートを低く設定しすぎてしまうと、システムの性能を著しく低下させてしまう危険性がありますし、逆にサンプリングレートを高く設定してしまうと、データの意味が無くなってしまうほどシステムの負荷が重くなります。そのため、 OProfile を入れることで性能を落とすことなく、かつ負荷が高くなりすぎないような値を探り、設定するようにしてください。
レポートを生成する前に、まずは operf
が停止していることを確認してください。また、 --session-dir
でデータのディレクトリを指定していない場合、 operf
はデータを カレントディレクトリ/oprofile_data/samples/current に書き込みます。なお、 opreport
や opannotate
のようなレポートツールは、既定で上述のディレクトリを使用します。
何もパラメータを指定しないで opreport
を実行すると、詳しい説明を表示することができます。オプションとして実行ファイル名を指定すると、その実行ファイルからのプロファイルデータのみを取得します。また C++ 言語で書かれたアプリケーションを解析したい場合は、 --demangle smart
オプションを指定してください。
opannotate
はソースコードからの注釈情報を生成します。下記のようなオプションを指定して実行してください:
#
opannotate
--source \ --base-dirs=ベースディレクトリ \ --search-dirs=検索ディレクトリ \ --output-dir=annotated/ \ /lib/libfoo.so
--base-dir
には、デバッグソースファイルから削除されたパス情報をカンマ区切りで指定します。ここで指定したパスは --search-dirs
で指定したパスよりも優先して検索されます。また、 --search-dirs
には、ソースファイルを検索するパスをカンマ区切りで指定します。
コンパイラの最適化の仕組みによってコードが削除されることがあるほか、別の場所に現れたりすることがあります。詳しい仕組みについては、 https://oprofile.sourceforge.net/doc/debug-info.html (英語) をお読みください。
本章では短い概要しか説明していません。詳しい情報を得るには、下記のリンク先を参照してください (いずれも英語のみの提供です):
プロジェクトの Web ページです。
様々なツールのオプションに関する詳しい説明が書かれています。
/usr/share/doc/packages/oprofile/oprofile.html
OProfile のマニュアルが配置されています。
Intel プロセッサ向けのアーキテクチャリファレンスです。