EmscriptenトレーシングAPIは、特にメモリ使用量に関して、アプリケーション内で何が起こっているかをよりよく把握するためのいくつかの便利な機能を提供します(これは、従来のブラウザのパフォーマンスツールでは利用できません)。
トレーシングAPIは、カスタムコレクションサーバー(詳細についてはサーバーの実行を参照)と通信するか、Google Web Tracing Frameworkと通信できます。Google Web Tracing Frameworkと通信する場合、利用可能なデータの一部が収集されます。
目次
トレーシングAPIを使用する場合は、コンパイルおよびリンクの各段階で--tracing
をemcc
に渡す必要があります。これにより、library_trace.js
ライブラリファイルが自動的に含まれ、プリプロセッサフラグ__EMSCRIPTEN_TRACING__
が設定されます。C / C++コードをビルドするためにclang
を直接呼び出す場合は、コードをビルドするときに-D__EMSCRIPTEN_TRACING__
を渡す必要があります。プリプロセッサフラグ__EMSCRIPTEN_TRACING__
が定義されていない場合、トレーシングAPIの実装はインラインの空のスタブによって提供されます。
また、トレーシングを有効にすると、libc
実装のdlmalloc.c
の実装が変更されるため、トレーシングAPIの使用に切り替える前に、手動でキャッシュをクリアすることをお勧めします。これを行わないと、完全なアロケーションの詳細が記録されません。このemcc
コマンドでキャッシュをクリアできます。
emcc --clear-cache
トレーシングAPIを初期化するには、emscripten_trace_configure()
を呼び出します。
emscripten_trace_configure("http://127.0.0.1:5000/", "MyApplication");
Google Web Tracing FrameworkでトレーシングAPIを使用するだけの場合は、代わりにemscripten_trace_configure_for_google_wtf()
を呼び出すことができます。
emscripten_trace_configure_for_google_wtf();
ユーザー名またはアプリケーションの特定のユーザーを識別する他の方法の概念がある場合は、それをトレーシングAPIに渡すことで、コレクターサーバーでのセッションの識別が容易になります。
emscripten_trace_set_session_username(username);
アプリケーション終了時にシャットダウンするには、emscripten_trace_close()
を呼び出すだけです。
emscripten_trace_close();
コンテキストは、アプリケーションのどの部分が現在実行されているかをトレーシングAPIに伝える方法です。コンテキストは、実際には現在のコンテキストのスタックとして維持されます。
コンテキストは、「物理演算の実行」のような大きなものから、「エンティティXのアニメーションの更新」のような小さなものまであります。
コンテキストスタックの粒度は、アプリケーションを計測するチームによって異なります。一部のアプリケーションでは、細かい粒度のコンテキストがより役立つ場合がありますが、大きなコンテキストの方が快適な場合があります。
すべてのトレーシング呼び出しでスタックトレースを取得するのではなく、現在のコンテキストスタックを見て代わりにそれを記録することがよくあります。これははるかに安価です。
コンテキストがサーバーによって完全に実装されると、各コンテキストで費やされた時間(プリミティブなプロファイリングメカニズム)、およびコンテキストがアクティブな間に割り当ておよび解放されたメモリの量も追跡するために使用されます。これにより、アプリケーションのどの部分がより多くのメモリを使用しているか、または多くの変動(およびおそらくヒープの断片化)を生み出しているかについての良いアイデアが得られるはずです。
コンテキストの開始と終了の記録は簡単です。
emscripten_trace_enter_context("Physics Update");
...
emscripten_trace_exit_context();
フレームまたはイベントループの開始と終了を記録することが重要です。これにより、トレーシングAPIは有用な追加分析を実行できます。
イベントループの開始を記録するのは簡単です。
emscripten_trace_record_frame_start();
そして、イベントループの終了を記録するのも簡単です。
emscripten_trace_record_frame_end();
すべてのアロケーションおよび解放操作は記録されるべきです。理想的には、データ型名も記録されるべきですが、これは現在手動で行う必要があります。
--tracing
を指定してビルドし、キャッシュをクリアすると、Emscripten がビルドする libc
は、malloc
、realloc
および free
へのすべての呼び出しを自動的に記録します。
データ型名の記録については、メモリを割り当てた後、アドレスに注釈を付けることができます。
emscripten_trace_annotate_address_type(model, "UI::Model");
さらに、一部のアプリケーションでは、追加のストレージのサイズを割り当てに関連付けたい場合があります。これは、emscripten_trace_associate_storage_size()
を介して行うことができます。
emscripten_trace_associate_storage_size(mesh, mesh->GetTotalMemoryUsage());
定期的に、ヒープ全体のレイアウトとメモリ使用量をトレース API に報告する必要があります。
これは 2 つの呼び出しで行われます。
emscripten_trace_report_memory_layout();
emscripten_trace_report_off_heap_data();
メッセージは、Emscripten トレース API を介してログに記録および記録できます。これらのメッセージには、チャネルと実際のメッセージの両方を含めることができます。チャネル名は、可視化インターフェース内でメッセージを分類およびフィルタリングするのに役立ちます。メッセージのログ記録中にヒープにメモリを割り当てることは避ける必要があります。
emscripten_trace_log_message("Application", "Started");
時間の経過とともに、可視化インターフェースは、これらのログメッセージを、時間経過に伴うメモリ使用量などの他のビューとより適切に関連付けるのに役立つように改善されます。新しいモデルやゲームアセットのロードなど、大量のメモリ アクティビティを引き起こす可能性のあるもののログを記録することは、メモリ使用量の動作パターンを分析する際に非常に役立ちます。
特定のタスクを記録および分析できます。タスクは通常、繰り返さない作業単位です。非同期的に実行される部分があるため、中断またはブロックされる場合があります。
タスクの例としては、通常、コールバックのチェーンを伴うアセットのロードがあります。
アプリケーションは、タスク ID (整数) を追跡し、それらが一意であることを確認する必要があります。
タスク ID は、ほとんどの呼び出しが現在のタスクで動作するため、タスクに関連するすべてのトレース呼び出しに渡す必要はありません。
タスクは、次で開始および停止できます。
emscripten_trace_task_start(taskID, name);
emscripten_trace_task_end();
タスクが中断/ブロックされている場合は、次で記録できます。
emscripten_trace_task_suspend("loading via HTTP");
そして、再開すると
emscripten_trace_task_resume(taskID, "parsing");
後でタスクデータを調べるときに使用するために、現在のタスクに追加のデータを関連付ける必要があるのが一般的です。この例としては、ロードされたアセットの URL があります。
emscripten_trace_task_associate_data("url", url);
アプリケーションで発生したエラーは、補助サービスとしてトレース API に報告できます。
emscripten_trace_report_error("Assertion failed: ...");
この機能は、Emscripten トレース API の将来の方向性を示すものとして含まれています。
emscripten-trace-collector サーバーのコピーを入手します。
README.rst の指示に従います。
Emscripten トレース API は、インストルメント化されたコードからデータを収集し、それをコレクターサーバーに送信します。サーバーはデータ分析も実行し、収集されたデータを表示するための Web インターフェースを提供します。
このクライアント/サーバー設計は、メモリが不足する可能性のある下位のハードウェア (32 ビット Windows マシンなど) でブラウザに干渉することなくツールを実行できるようにすることを目的としています。
この設計により、1 つのサーバーを実行して、さまざまなクライアントからデータを収集することもできます。
データはバッチ処理され、1 秒に約 1 回または 2 回のチャンクでサーバーに送信されます。これにより、記録されるすべてのイベントに対してサーバーへの新しい接続を開く必要がなくなります。
Emscripten トレース API を使用する場合、ヒープを乱す可能性のある操作を実行しないように注意する必要があります。たとえば、emscripten_trace_log_message()
に渡す文字列を割り当てるべきではありません。それは、割り当てが追跡され、分析しようとしている動作や結果が乱れる可能性があるためです。
このため、Emscripten トレース API は、独自のすべてのデータを Emscripten ヒープから外し、Emscripten ヒープへの書き込みを実行しません。
emscripten_trace_configure
(const char *collector_url, const char *application)¶collector_url (const char*) – コレクターサーバーのベース URL。
application (const char*) – トレース対象のアプリケーションの名前。
void
コレクターサーバーへの接続を構成します。
これは、アプリケーションが開始された後に行われる最初の操作の 1 つである必要があります。
ほとんどの場合、collector_url
は http://127.0.0.1:5000/
になります。
emscripten_trace_configure_for_google_wtf
(void)¶void
Google Web Tracing Framework と通信するようにトレースを構成します。
トレースのすべての機能が Google WTF ツール内で利用できるわけではありません。(現在、コンテキスト、ログメッセージ、マークのみ。)
emscripten_trace_set_enabled
(bool enabled)¶enabled (bool) – トレースが有効かどうか。
void
トレースが有効かどうかを設定します。このオプションを使用してトレースを無効にすると、メモリ使用量に関して不正確なデータが収集される可能性があります。
emscripten_trace_set_session_username
(const char *username)¶username (const char*) – アプリケーションを実行している人のユーザー名。
void
これは、複数のユーザーがコレクターサーバーを使用しており、タイムスタンプ付きのセッション ID 以外に個々のセッションを識別したい場合に役立ちます。
これは、トレースがすでに開始された後に設定できるため、ユーザーがログインまたは認証プロセスを完了した後に設定しても問題ありません。
emscripten_trace_record_frame_start
(void)¶void
これは、フレーム/イベントループの開始時に呼び出す必要があります。
現在のタイムスタンプは、このデータに関連付けられています。
サーバーはこれを使用して、フレーム時間 (したがって、1 秒あたりのフレーム数) を追跡し、フレーム処理中に発生するメモリ操作を考慮します。
emscripten_trace_record_frame_end
(void)¶void
これは、フレーム/イベントループの終了時に呼び出す必要があります。
現在のタイムスタンプは、このデータに関連付けられています。
サーバーはこれを使用して、フレームへのメモリ操作と経過時間の蓄積を停止します。
emscripten_trace_log_message
(const char *channel, const char *message)¶channel (const char*) – 発行されるタイムラインイベントのカテゴリ。
message (const char*) – 発行されるタイムラインイベントの説明。
void
ログメッセージを記録します。これは、メモリ使用量やフレームレートの変化と相関させて把握することが有利になる可能性のあるイベントやアクションを記録するのに役立ちます。
現在のタイムスタンプは、このデータに関連付けられています。
サーバーは、このデータに対してまだ十分な処理を行っていません。これは将来改善されます。
emscripten_trace_mark
(const char *message)¶message (const char *) – 発行されるマークの名前。
void
タイムラインにマークを記録します。これは主に Google Web Tracing Framework で使用するためのものです。
現在のタイムスタンプは、このデータに関連付けられています。
emscripten_trace_report_error
(const char *error)¶error (const char*) – 報告されるエラーメッセージ。
void
API は現在のコールスタックを取得し、それをサーバーへのレポートに含めます。
現在のタイムスタンプは、このデータに関連付けられています。
これは、JavaScript および web-worker エラーのキャプチャや、C/C++ コード内からの失敗したアサーションまたはその他のランタイムエラーなど、さまざまなことに使用できます。
emscripten_trace_record_allocation
(const void *address, int32_t size)¶address (const void*) – 割り当てられたメモリアドレス。
size (int32_t) – 割り当てられたメモリブロックのサイズ。
void
これは、すべてのメモリ割り当てに対して必ず呼び出す必要があります。これを行うのに最適な場所は、Emscripten の dlmalloc
実装内です。
現在のタイムスタンプは、このデータに関連付けられています。
emscripten_trace_record_reallocation
(const void *old_address, const void *new_address, int32_t size)¶old_address (const void*) – 再割り当てされたメモリブロックの古いアドレス。
new_address (const void*) – 再割り当てされたメモリブロックの新しいアドレス。
size (int32_t) – 再割り当てされたメモリブロックの新しいサイズ。
void
これは、すべてのメモリ再割り当てに対して必ず呼び出す必要があります。これを行うのに最適な場所は、Emscripten の dlmalloc
実装内です。
現在のタイムスタンプは、このデータに関連付けられています。
emscripten_trace_record_free
(const void *address)¶address (const void*) – 解放されるメモリのアドレス。
void
これは、すべての free
操作に対して必ず呼び出す必要があります。これを行うのに最適な場所は、Emscripten の dlmalloc
実装内です。
現在のタイムスタンプは、このデータに関連付けられています。
また、1 回の free
操作に対して複数回呼び出さないことも重要です。
emscripten_trace_annotate_address_type
(const void *address, const char *type)¶address (const void*) – アノテーションを付けるべきメモリアドレス。
type (const char*) – 割り当てられているデータ型の名前。
void
アドレスに、そこに格納されているデータ型の名前をアノテーションとして付けます。これは、サーバーがメモリ内の内容を分析するのに役立てるために使用されます。
emscripten_trace_associate_storage_size
(const void *address, int32_t size)¶address (const void*) – アノテーションを付けるべきメモリアドレス。
size (int32_t) – この割り当てに関連付けられたメモリのサイズ。
void
このアドレスに追加のストレージ量を関連付けます。これは割り当て自体のサイズを表すものではなく、このオブジェクトのサイズを検討する際に考慮に入れるべき関連メモリを表します。
この関連付けられたストレージは、アプリケーション固有の性質を持ちます。
例として、オブジェクトにベクターまたは文字列が含まれている場合、メモリ使用量を分析する際にそれを認識したい場合があります。これは、サーバーに追加のストレージを認識させる方法を提供します。
emscripten_trace_report_memory_layout
(void)¶void
これは、通常の Emscripten ヒープの使用状況を報告するために、定期的に呼び出す必要があります。これにより、スタックと動的メモリの使用状況、および総メモリサイズの詳細が提供されます。
現在のタイムスタンプは、このデータに関連付けられています。
emscripten_trace_report_off_heap_data
(void)¶void
これは、通常の Emscripten ヒープの一部ではないメモリの使用状況を報告するために、定期的に呼び出す必要があります。これは現在、OpenAL のメモリ使用量を報告するために使用されています。
現在のタイムスタンプは、このデータに関連付けられています。
サーバーはまだこのデータを表示しません。
emscripten_trace_enter_context
(const char *name)¶name (const char*) – コンテキスト名。
void
現在のタイムスタンプは、このデータに関連付けられています。
emscripten_trace_exit_context
(void)¶void
現在のタイムスタンプは、このデータに関連付けられています。
void emscripten_trace_task_start(int task_id, const char *name);
task_id (int) – タスク ID
name (const char*) – タスク名
void
タスクが開始されます。タスク ID はアプリケーションのライフサイクルを通じて一意である必要があります。アプリケーションによって管理/追跡される必要があります。
現在のタイムスタンプは、このデータに関連付けられています。
void emscripten_trace_task_associate_data(const char *key, const char *value);
key (const char*) – キー
value (const char*) – 値
void
キーと値のペアを現在のタスクに関連付けます。
void emscripten_trace_task_suspend(const char *explanation);
explanation (const char*) – タスクが中断される理由。
void
現在のタスクが中断されます。
説明は、タスクが中断される理由を示す必要があります。これにより、タスクの履歴を表示するときにこの情報を利用できるようにします。
現在のタイムスタンプは、このデータに関連付けられています。
void emscripten_trace_task_resume(int task_id, const char *explanation);
task_id (int) – タスク ID
explanation (const char*) – タスクが再開される理由。
void
task_id
で識別されるタスクが再開され、現在のタスクになります。
説明は、タスクが再開されて何を行うかを示す必要があります。これにより、タスクの履歴を表示するときにこの情報を利用できるようにします。
現在のタイムスタンプは、このデータに関連付けられています。
void emscripten_trace_task_end(void);
void
現在のタスクが終了します。
現在のタイムスタンプは、このデータに関連付けられています。
emscripten_trace_close
(void)¶void
これは、アプリケーションの終了時に閉じる必要があります。これにより、サーバーへのフラッシュが確実に行われ、トレースコードが終了します。