この章では Objective Caml プログラムの実行をプロファイルする方法を解説します。プロファイルとは、関数が何回 call されたか、条件分岐が成立したか否かを記録することです。
17.1 |
Compiling for profiling |
|
実行をプロファイルする前に、ocamlc コンパイラのフロントエンドである ocamlcp を使ってプログラムをプロファイルモードでコンパイルしなければなりません (8) 章を見て下さい) 。モジュールを分割コンパイルする場合、ocamlcp でモジュールをコンパイルして .cmo ファイルを生成してください。これをリンクするときも ocamlcp を使用できます (これは必ずしも必要ではありません) 。
Note
モジュール (.ml ファイル) に対応するインターフェイス (.mli ファイル) がない場合、ocamlcp はオブジェクトファイル (.cmi と .cmo) を出力しますが、これらは ocamlc が出力するものと互換性がありません。このせいで、プロファイルコンパイルと通常のコンパイルを切り替える際問題が発生することがあります。これを避けるためには、常にそれぞれの .ml ファイルに対応する .mli ファイルを用意するようにしてください。
Note
プログラムをプロファイルモードでコンパイルする場合、__ocaml_prof で始まる識別子は使用しないでください。
プロファイル情報の量は ocamlcp への -p オプションで指定できます。プログラムをプロファイルするべき部分を指定する文字を以下に示します。
-
a
- すべてのオプションを有効にします
- f
- 関数呼び出し : カウントポイントを関数本体の先頭に配置します
- i
- if ...then ...else ... : カウントポイントを then の分岐先と else の分岐先に配置します
- l
- while, for ループ : カウントポイントをループ本体の先頭に配置します
- m
- match 分岐 : カウントポイントをそれぞれの分岐先の先頭に配置します
- t
- try ...with ... 分岐 : カウントポイントをすべての分岐先の先頭に配置します
例えば、ocamlcp -p film でコンパイルした場合関数呼び出し、if...then...else... 、ループ、パターンマッチングをプロファイルします。
ocamlcp を -p オプションなしで実行した場合、デフォルトで -p fm を指定したことになります。つまり関数呼び出しとパターンマッチングをプロファイルします。
Note:
ストリームの実装と syntactic sugar としてのストリームのパターンのため、ストリームの式とパターンの部分をプロファイルして得られた結果を、指定されたフラグとあわせて予想するのは困難です。ストリームを使用するプログラムをプロファイルするときは ocamlcp -p a とすることを推奨します。
17.2 |
Profiling an execution |
|
ocamlcp でコンパイルされたバイトコード実行ファイルは、指定された項目の実行回数を記録し、それをカレントディレクトリの ocamlprof.dump というファイルに保存します。
ocamlprof.dump ファイル は exit が呼ばれたり、中止したりした場合のみ保存されます。uncaught exception が発生した場合は保存されません。
カレントディレクトリにすでにダンプファイルがあった場合は、既存の情報に新しいプロファイル情報を追加します。異なる入力を与えて実行し、複数のプロファイル結果を得ることなどが出来ます。
17.3 |
Printing profiling information |
|
ocamlprof コマンドは、プログラムソースに実行回数をコメントとして挿入します。例えば、
ocamlprof foo.ml
とすると foo モジュールのソースコードに、各関数が何回コールされたかをコメントとして挿入します。もちろん、プロファイル実行したのちソースコードに変更を加えた場合、この情報は間違っていることになります。
ocamlprof には以下のオプションがあります。
-
-f dumpfile
-
プロファイル情報のダンプファイルとして使用するファイルを指定する。
- -F string
-
プロファイル情報の出力に追加する文字列を指定する。デフォルトで ocamlprof は、実行回数 n の箇所に (* n *) という形のコメントを挿入しますが、オプションで -F s と指定すると (* sn *) と出力するようになります、
ocamlprof によるプロファイルでは、各関数の実行回数の記録のみで実行時間は記録されません。ocamlc に生成されたバイトコードの実行時間をプロファイルする方法は現在のところありません。
ocamlopt に生成されたネイティブコードならば、-p オプションと Unix の標準プロファイラ gprof を使うことで実行時間と実行回数を記録できます。コンパイルとリンク時に -p を追加するだけです。
ocamlopt -o myprog -p other-options files
./myprog
gprof myprog
gprof の出力中にある Caml の関数名は以下のフォーマットになっています。
Module-name_function-name_unique-number
このフォーマットに従っていない関数は Caml のランタイムシステムの関数か、プログラムにリンクされた外部の C 関数です。
gprof の出力の見方は Unix マニュアルの gprof(1) のページに詳しく書かれています。一般的な gprof の出力は、各関数の実行時間や実行回数を記した "flat" プロファイルと、コール・グラフのある "hierarchical" プロファイルの 2 つのプロファイルで構成されています。現在、ocamlopt がこの 2 つのプロファイルを両方サポートしているプラットフォームは Intel x86/Linux と Alpha/Digital だけです。その他の環境では "flat" プロファイルの実行時間情報しか出力されません。また gprof は経験則に基づいた時間評価を行っているため、その出力は不正確である可能性があるということを忘れないで下さい。