trace.h

EmscriptenトレーシングAPIは、特にメモリ使用量に関して、アプリケーション内で何が起こっているかをよりよく把握するためのいくつかの便利な機能を提供します(これは、従来のブラウザのパフォーマンスツールでは利用できません)。

トレーシングAPIは、カスタムコレクションサーバー(詳細についてはサーバーの実行を参照)と通信するか、Google Web Tracing Frameworkと通信できます。Google Web Tracing Frameworkと通信する場合、利用可能なデータの一部が収集されます。

使用法

コンパイラとの対話

トレーシングAPIを使用する場合は、コンパイルおよびリンクの各段階で--tracingemccに渡す必要があります。これにより、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 は、mallocrealloc および 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 トレース API は、インストルメント化されたコードからデータを収集し、それをコレクターサーバーに送信します。サーバーはデータ分析も実行し、収集されたデータを表示するための Web インターフェースを提供します。

このクライアント/サーバー設計は、メモリが不足する可能性のある下位のハードウェア (32 ビット Windows マシンなど) でブラウザに干渉することなくツールを実行できるようにすることを目的としています。

この設計により、1 つのサーバーを実行して、さまざまなクライアントからデータを収集することもできます。

データのバッチ処理

データはバッチ処理され、1 秒に約 1 回または 2 回のチャンクでサーバーに送信されます。これにより、記録されるすべてのイベントに対してサーバーへの新しい接続を開く必要がなくなります。

ヒープを乱さないでください

Emscripten トレース API を使用する場合、ヒープを乱す可能性のある操作を実行しないように注意する必要があります。たとえば、emscripten_trace_log_message() に渡す文字列を割り当てるべきではありません。それは、割り当てが追跡され、分析しようとしている動作や結果が乱れる可能性があるためです。

このため、Emscripten トレース API は、独自のすべてのデータを Emscripten ヒープから外し、Emscripten ヒープへの書き込みを実行しません。

関数

void emscripten_trace_configure(const char *collector_url, const char *application)
パラメータ
  • collector_url (const char*) – コレクターサーバーのベース URL。

  • application (const char*) – トレース対象のアプリケーションの名前。

戻り値の型

void

コレクターサーバーへの接続を構成します。

これは、アプリケーションが開始された後に行われる最初の操作の 1 つである必要があります。

ほとんどの場合、collector_urlhttp://127.0.0.1:5000/ になります。

void emscripten_trace_configure_for_google_wtf(void)
戻り値の型

void

Google Web Tracing Framework と通信するようにトレースを構成します。

トレースのすべての機能が Google WTF ツール内で利用できるわけではありません。(現在、コンテキスト、ログメッセージ、マークのみ。)

void emscripten_trace_set_enabled(bool enabled)
パラメータ
  • enabled (bool) – トレースが有効かどうか。

戻り値の型

void

トレースが有効かどうかを設定します。このオプションを使用してトレースを無効にすると、メモリ使用量に関して不正確なデータが収集される可能性があります。

void emscripten_trace_set_session_username(const char *username)
パラメータ
  • username (const char*) – アプリケーションを実行している人のユーザー名。

戻り値の型

void

これは、複数のユーザーがコレクターサーバーを使用しており、タイムスタンプ付きのセッション ID 以外に個々のセッションを識別したい場合に役立ちます。

これは、トレースがすでに開始された後に設定できるため、ユーザーがログインまたは認証プロセスを完了した後に設定しても問題ありません。

void emscripten_trace_record_frame_start(void)
戻り値の型

void

これは、フレーム/イベントループの開始時に呼び出す必要があります。

現在のタイムスタンプは、このデータに関連付けられています。

サーバーはこれを使用して、フレーム時間 (したがって、1 秒あたりのフレーム数) を追跡し、フレーム処理中に発生するメモリ操作を考慮します。

void emscripten_trace_record_frame_end(void)
戻り値の型

void

これは、フレーム/イベントループの終了時に呼び出す必要があります。

現在のタイムスタンプは、このデータに関連付けられています。

サーバーはこれを使用して、フレームへのメモリ操作と経過時間の蓄積を停止します。

void emscripten_trace_log_message(const char *channel, const char *message)
パラメータ
  • channel (const char*) – 発行されるタイムラインイベントのカテゴリ。

  • message (const char*) – 発行されるタイムラインイベントの説明。

戻り値の型

void

ログメッセージを記録します。これは、メモリ使用量やフレームレートの変化と相関させて把握することが有利になる可能性のあるイベントやアクションを記録するのに役立ちます。

現在のタイムスタンプは、このデータに関連付けられています。

サーバーは、このデータに対してまだ十分な処理を行っていません。これは将来改善されます。

void emscripten_trace_mark(const char *message)
パラメータ
  • message (const char *) – 発行されるマークの名前。

戻り値の型

void

タイムラインにマークを記録します。これは主に Google Web Tracing Framework で使用するためのものです。

現在のタイムスタンプは、このデータに関連付けられています。

void emscripten_trace_report_error(const char *error)
パラメータ
  • error (const char*) – 報告されるエラーメッセージ。

戻り値の型

void

API は現在のコールスタックを取得し、それをサーバーへのレポートに含めます。

現在のタイムスタンプは、このデータに関連付けられています。

これは、JavaScript および web-worker エラーのキャプチャや、C/C++ コード内からの失敗したアサーションまたはその他のランタイムエラーなど、さまざまなことに使用できます。

void emscripten_trace_record_allocation(const void *address, int32_t size)
パラメータ
  • address (const void*) – 割り当てられたメモリアドレス。

  • size (int32_t) – 割り当てられたメモリブロックのサイズ。

戻り値の型

void

これは、すべてのメモリ割り当てに対して必ず呼び出す必要があります。これを行うのに最適な場所は、Emscripten の dlmalloc 実装内です。

現在のタイムスタンプは、このデータに関連付けられています。

void 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 実装内です。

現在のタイムスタンプは、このデータに関連付けられています。

void emscripten_trace_record_free(const void *address)
パラメータ
  • address (const void*) – 解放されるメモリのアドレス。

戻り値の型

void

これは、すべての free 操作に対して必ず呼び出す必要があります。これを行うのに最適な場所は、Emscripten の dlmalloc 実装内です。

現在のタイムスタンプは、このデータに関連付けられています。

また、1 回の free 操作に対して複数回呼び出さないことも重要です。

void emscripten_trace_annotate_address_type(const void *address, const char *type)
パラメータ
  • address (const void*) – アノテーションを付けるべきメモリアドレス。

  • type (const char*) – 割り当てられているデータ型の名前。

戻り値の型

void

アドレスに、そこに格納されているデータ型の名前をアノテーションとして付けます。これは、サーバーがメモリ内の内容を分析するのに役立てるために使用されます。

void emscripten_trace_associate_storage_size(const void *address, int32_t size)
パラメータ
  • address (const void*) – アノテーションを付けるべきメモリアドレス。

  • size (int32_t) – この割り当てに関連付けられたメモリのサイズ。

戻り値の型

void

このアドレスに追加のストレージ量を関連付けます。これは割り当て自体のサイズを表すものではなく、このオブジェクトのサイズを検討する際に考慮に入れるべき関連メモリを表します。

この関連付けられたストレージは、アプリケーション固有の性質を持ちます。

例として、オブジェクトにベクターまたは文字列が含まれている場合、メモリ使用量を分析する際にそれを認識したい場合があります。これは、サーバーに追加のストレージを認識させる方法を提供します。

void emscripten_trace_report_memory_layout(void)
戻り値の型

void

これは、通常の Emscripten ヒープの使用状況を報告するために、定期的に呼び出す必要があります。これにより、スタックと動的メモリの使用状況、および総メモリサイズの詳細が提供されます。

現在のタイムスタンプは、このデータに関連付けられています。

void emscripten_trace_report_off_heap_data(void)
戻り値の型

void

これは、通常の Emscripten ヒープの一部ではないメモリの使用状況を報告するために、定期的に呼び出す必要があります。これは現在、OpenAL のメモリ使用量を報告するために使用されています。

現在のタイムスタンプは、このデータに関連付けられています。

サーバーはまだこのデータを表示しません。

void emscripten_trace_enter_context(const char *name)
パラメータ
  • name (const char*) – コンテキスト名。

戻り値の型

void

現在のタイムスタンプは、このデータに関連付けられています。

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

現在のタスクが終了します。

現在のタイムスタンプは、このデータに関連付けられています。

void emscripten_trace_close(void)
戻り値の型

void

これは、アプリケーションの終了時に閉じる必要があります。これにより、サーバーへのフラッシュが確実に行われ、トレースコードが終了します。