ツールチェーンのプロファイリング

ツールチェーンは、外部ツールやサブライブラリと適度な量でやり取りします。正確なセットは、一般的に使用されたコンパイルおよびリンカフラグによって異なります。異常なコンパイル時間が見られる場合、またはEmscriptenツールチェーン自体を開発している場合は、プロジェクトをコンパイルする際のツールチェーンのパフォーマンス自体をプロファイリングすると役立つ場合があります。Emscriptenには、この目的で使用できるツールチェーン全体にわたるemprofile.pyプロファイラが組み込まれています。

簡単な例

ツールチェーンプロファイラを試すには、次のコマンドセットを実行します。

cd path/to/emscripten
export EMPROFILE=1
emcc test/hello_world.c -O3 -o a.html
emprofile

Windowsでは、exportキーワードをsetに置き換えます。最後のコマンドは、toolchain_profiler.results_yyyymmdd_hhmm.html形式のHTMLファイルを生成する必要があります。このファイルは、Webブラウザで開いて結果を表示できます。

詳細

環境変数EMPROFILE=1が設定されている場合、ツールチェーンが呼び出されると常にツールチェーンプロファイラがアクティブになります。このモードでは、呼び出された各ツールは、Emscriptenの一時ディレクトリにある一連の.jsonファイルにプロファイリング計装データを蓄積します。

プロファイリングツールのコマンド

コマンドtools/emprofile.py --clearは、以前に保存されたすべてのプロファイリングデータを削除します。このコマンドを呼び出して、プロファイリングセッションを新しい空の状態に消去します。プロファイリングを開始するには、環境変数EMPROFILE=1を設定してEmscriptenツールのコマンドを呼び出します。例に示すようにシステム全体で設定するか、次のようにコマンドごとに設定します。

emprofile --clear
EMPROFILE=1 emcc -c foo.c a.o
EMPROFILE=1 emcc a.o -O3 -o a.html
emprofile --outfile=myresults.html

1つのセッション内で任意の数のコマンドをプロファイリングでき、emprofileが最終的に呼び出されると、その時点までのすべてのEmscriptenツールの呼び出しからのレコードを収集し、グラフ化し、次回実行のために記録されたプロファイリングデータをクリアします。

出力HTMLファイル名は、オプションの--outfile=myresults.htmlパラメータで選択できます。

Pythonスクリプトのインストルメンテーション

Pythonプロファイリングブロック

サブプロセスの開始時間と終了時間だけをグラフ化するのは、何が起こっているのかを把握するには、場合によっては粗すぎる場合があります。Pythonコードでは、実行をカスタムタスクに分割するために、コードの個々のブロックに階層的に注釈を付けることができます。これらのブロックは、出力グラフで青色で表示されます。カスタムプロファイリングブロックを追加するには、Pythonのwithキーワードを使用してprofile_blockセクションを追加します。

with ToolchainProfiler.profile_block('my_custom_task'):
  do_some_tasks()
  call_another_function()
  more_code()

this_is_outside_the_block()

これにより、同じスコープ内の3つの関数が、プロファイリングスイムレーンで青色で描画されたブロック「my_custom_task」の下に表示されます。

場合によっては、withセクション内にコードをラップするのが面倒な場合があります。このようなシナリオでは、低レベルのCスタイルのenter_blockステートメントとexit_blockステートメントを使用することもできます。

ToolchainProfiler.enter_block('my_code_block')
try:
  do_some_tasks()
  call_another_function()
  more_code()
finally:
  ToolchainProfiler.exit_block('my_code_block')

ただし、この形式を使用する場合は、すべてのコードフローでToolchainProfiler.enter_block()への呼び出しがToolchainProfiler.exit_block()への呼び出しと正確に一致するように注意する必要があります。そのため、コードをtry-finallyステートメントでラップすることをお勧めします。