Version: 2020.1
言語: 日本語
Video Profiler モジュール
ログファイル

低レベルのネイティブプラグイン Profiler API

Unity Profiler は、アプリケーションのパフォーマンスを分析し、改善するためのツールです。Profiler は、アプリケーションの Unity ネイティブコードやマネージコードの関数呼び出しの フレーム時間分析 を実行します。ProfilerMarker API を使用して独自のコードにタイミングマーカーを挿入することで、アプリケーションの特定エリアのパフォーマンスをより深く理解することができます。

低レベルのネイティブプラグイン プロファイラー API を使用して、プロファイラを拡張し、ネイティブプラグインコードのパフォーマンスをプロファイルしたり、Razor(PS4)、PIX(Xbox、Windows)、Chrome Tracing、ETW、ITT、Vtune、Telemetry などのサードパーティのプロファイリングツールに送信するプロファイリングデータを準備することができます。低レベルのネイティブプラグイン Profiler API は、Unity Profiler と外部ツール間の通信のために以下のインターフェースを提供します。

  • IUnityProfiler: C/C++ ネイティブプラグインコードから Unity Profiler にインストルメンテーションイベントを追加するには、このインターフェースを使用します。
  • IUnityProfilerCallbacks: このインターフェースを使用して、Unity Profiler のイベントのインターセプト、保存、他のツールへのリダイレクトを行います。

IUnityProfiler API

IUnityProfiler プラグイン API を使用して、ネイティブプラグインの C/C++ コードにインストルメンテーションを追加します。

プラグインAPI は IUnityProfiler インターフェースで表現されており、IUnityProfiler.h ヘッダーで宣言されています。Unity はこのヘッダーを、Unity インストールの<UnityInstallPath>\Editor\Data\PluginAPI フォルダーに格納します。(macOS では、Unity アプリケーションを右クリックして、Show Package Contents を選択してください。ヘッダーは Contents\PluginAPI にあります。)

メソッド 説明 
CreateMarker 名前の付いたインストルメンテーションスコープを表すプロファイラーマーカーを作成します。これを使ってインストルメンテーションサンプルを生成できます。
SetMarkerMetadataName プロファイラーマーカーのインストルメンテーションサンプルと一緒に渡すことができるカスタム製のパラメーター名を指定します。
BeginSample プロファイラーマーカーにちなんで名付けられたコードのインストルメンテーションセクションを開始します。
EndSample インストルメンテーションセクションを終了します。
EmitEvent メタデータ付きの汎用イベントを発信します。
IsEnabled プロファイラーがデータを取得している場合は 1 を返します。
IsAvailable プロファイラーが利用可能なエディターまたは開発用プレーヤーには 1 を、リリース用プレイヤーには 0 を返します。
RegisterThread 現在のスレッドを指定された名前で登録します。
UnregisterThread プロファイラーから現在のスレッドの登録を解除します。

使用例

この例では、プロファイラーイベントを生成し、Profiler ウィンドウに表示します。

# include <IUnityInterface.h>
# include <IUnityProfiler.h>

static IUnityProfiler* s_UnityProfiler = NULL;
static const UnityProfilerMarkerDesc* s_MyPluginMarker = NULL;
static bool s_IsDevelopmentBuild = false;

static void MyPluginWorkMethod()
{
    if (s_IsDevelopmentBuild)
        s_UnityProfiler->BeginSample(s_MyPluginMarker);

    // Unity Profiler で "MyPluginMethod" として表示したいコード
    // ...

    if (s_IsDevelopmentBuild)
        s_UnityProfiler->EndSample(s_MyPluginMarker);
}

extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
    s_UnityProfiler = unityInterfaces->Get<IUnityProfiler>();
    if (s_UnityProfiler == NULL)
        return;
    s_IsDevelopmentBuild = s_UnityProfiler->IsAvailable() != 0;
    s_UnityProfiler->CreateMarker(&s_MyPluginMarker, "MyPluginMethod", kUnityProfilerCategoryOther, kUnityProfilerMarkerFlagDefault, 0);
}

extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload()
{
    s_UnityProfiler  = NULL;
}

IUnityProfilerCallbacks API コールバック

ネイティブの Profiler プラグイン API は、Unity のサブシステムとサードパーティのプロファイリング API との間のインターフェースを提供します。そのため、外部のプロファイリング ツールを使用して Unity アプリケーションのプロファイリングを行うことができます。IUnityProfilerCallbacks ヘッダーが API を公開しており、Unity はこの API を、Unity インストールの <UnityInstallPath>\Editor\Data\PluginAPI フォルダーに格納します。(macOS では、Unity アプリケーションを右クリックして、Show Package Contents を選択します。ヘッダーは Contents\PluginAPI にあります)。

以下の Unity Profiler の機能は、インストルメンテーションデータの取得に役立ち、アプリケーションのパフォーマンスを分析することができます。

プロファイラー機能 説明 
カテゴリ Unity はプロファイルデータをカテゴリ (レンダリング、スクリプティング、アニメーションなど) にグループ化し、各カテゴリに色を割り当てます。色分けされたカテゴリは、Profiler ウィンドウでデータの種類を視覚的に区別するのに役立ちます。Profiler ネイティブプラグイン API を使用すると、これらの色を取得して外部のプロファイリングツールで使用することができます。
Usage フラグ usage フラグは、Unity が外部プロファイリングツールに送信するデータ量を減らすフィルターとして機能します。usage フラグを使うと、プロファイリングデータを外部ツールに送信する前に、不要な情報を削除することができます。

Availability フラグ はマーカーが Unity Editor、開発用プレーヤー、またはリリース用プレイヤーで利用可能かを示すフラグです。

Verbosity レベル は、エディターで行っているタスクのタイプと、そのタスクが必要とする情報のレベル (内部、デバッグ、ユーザーレベルなど) に関連します。
フレームイベント プロファイラーのネイティブプラグイン API を使用して、外部のプロファイリングツールでフレームタイムの解析を行うことができます。
スレッドプロファイリング Unity は著しい量の作業をスレッドで行います (例えば、メインスレッド、レンダースレッド、ジョブシステムワーカー スレッドなど)。プロファイラーのネイティブプラグイン API を使用すると、どのスレッドでもプロファイリングを行うことができます。

Unity Profiler が生成するインストルメンテーションデータを外部のプロファイラーで使用するために、以下の最小限のコールバックを、サードパーティのプロファイラーを統合する C/C++ プラグインコードで使用できます。

コールバック 機能
RegisterCreateCategoryCallback IUnitePrfilerCreateCategoryCallback コールバックを登録し、Unity がカテゴリを作成するたびにプロファイラーのカテゴリ名と色を取得します。
RegisterCreateMarkerCallback IUnityPrfilerCreateMarkerCallback コールバックを登録します。これは、Unity がマーカーを作成するたびに呼び出されます。このコールバックを使用して、マーカーの名前、Profiler カテゴリ、usage フラグを取得します。コールバック関数の const UnityProfilerMarkerDesc* markerDesc パラメーターは、RegisterMarkerEventCallback でマーカーをフィルタリングするために使用するマーカー記述 (marker description) への永続的なポインターを表します。
RegisterMarkerEventCallback IUnitionProfilerMarkerEventCallback コールバックを登録します。これは、シングルショット、スコープ付き、メモリ割り当て、またはガベージコレクションのイベントが発生したときに呼び出されます。ノート: Unity はメモリ割り当てイベントを GC.Alloc マーカーで、ガベージコレクションイベントを GC.Collect マーカーで表します。
RegisterFrameCallback サンプルを論理フレームにカプセル化し、フレームを使用しない外部のプロファイリングツールがこれらのサンプルを使用可能にします。また、Unity が次の論理的な CPU フレームを開始したときに、Unity Profiler が実行するコールバックを登録します。
RegisterCreateThreadCallback Unity がプロファイリング用のスレッドを登録するたびに、内部スレッド名を取得するコールバックを登録します。

使用例

この例では、Unity Profiler のイベントを、Push/Pop セマンティクスを持つ別のプロファイラーに渡す方法を示しています。以下の 2 つの関数を用意しています。

  • void MyProfilerPushMarker(const char* name) - 名前付きのマーカーをプッシュします。 void MyProfilerPopMarker() - インストルメンテーションマーカーを表示します。

次の例では、Unity Profiler から外部のプロファイラーにインストルメンテーションの開始と終了のイベントを渡すために、必要最小限の実装を行っています。

# include <IUnityInterface.h>
# include <IUnityProfilerCallbacks.h>

static IUnityProfilerCallbacks* s_UnityProfilerCallbacks = NULL;

static void UNITY_INTERFACE_API MyProfilerEventCallback(const UnityProfilerMarkerDesc* markerDesc, UnityProfilerMarkerEventType eventType, unsigned short eventDataCount, const UnityProfilerMarkerData* eventData, void* userData)
{
    switch (eventType)
    {
        case kUnityProfilerMarkerEventTypeBegin:
        {
            MyProfilerPushMarker(markerDesc->name);
            break;
        }
        case kUnityProfilerMarkerEventTypeEnd:
        {
            MyProfilerPopMarker();
            break;
        }
    }
}

static void UNITY_INTERFACE_API MyProfilerCreateMarkerCallback(const UnityProfilerMarkerDesc* markerDesc, void* userData)
{
    s_UnityProfilerCallbacks->RegisterMarkerEventCallback(markerDesc, MyProfilerEventCallback, NULL);
}

extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
    s_UnityProfilerCallbacks = unityInterfaces->Get<IUnityProfilerCallbacks>();
    s_UnityProfilerCallbacks->RegisterCreateMarkerCallback(&MyProfilerCreateMarkerCallback, NULL);
}

extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload()
{
    s_UnityProfilerCallbacks->UnregisterCreateMarkerCallback(&MyProfilerCreateMarkerCallback, NULL);
    s_UnityProfilerCallbacks->UnregisterMarkerEventCallback(NULL, &MyProfilerEventCallback, NULL);
}

ノート: すべてのマーカーから指定するコールバックを登録解除するには、最初のパラメーターを null に設定して UnregisterEventCallback を実行します。

UnitySystracePlugin の例

フレームごとに 1 回づつ、マーカコールバックを動的に登録および登録解除できます。次の例は、サードパーティのプロファイルの状況に応じて、コールバックを有効または無効にすることによって、プロファイリングのオーバーヘッドを最小化する方法を示しています。

| static void UNITY_INTERFACE_API SystraceFrameCallback(void* userData)
{
    bool isCapturing = ATrace_isEnabled();
    if (isCapturing != s_isCapturing)
    {
        s_isCapturing = isCapturing;
        if (isCapturing)
        {
            s_UnityProfilerCallbacks->
              RegisterCreateMarkerCallback(SystraceCreateEventCallback, NULL);
        }
        else
        {
            s_UnityProfilerCallbacks->
              UnregisterCreateMarkerCallback(SystraceCreateEventCallback, NULL);
            s_UnityProfilerCallbacks->
              UnregisterMarkerEventCallback(NULL, SystraceEventCallback, NULL);
        }
    }
}

ノート: すべてのマーカーから指定するコールバックを登録解除するには、最初のパラメーターを null に設定して UnregisterEventCallback を実行します。

特別なマーカー

Unity には有用なメタデータを含む以下の特別なマーカーがあります。

  • Profiler.DefaultMarker
  • GC.Alloc

Profiler.DefaultMarker

Profiler.DefaultMarker は、Unity が Profiler.BeginSampleProfiler.EndSample のイベントのために予約しているマーカーです。

上の例では、kUnityProfilerMarkerEventTypeBegin eventType は、Profiler.BeginSample イベントに対応しており、以下のデータを持っています。

  • Int32: UnityEngine.Object インスタンス ID。オブジェクトが指定されていない場合は 0 です。
  • UInt16 array: Profiler.BeginSample に渡されるUTF16 文字列。サイズはバイト数です。
  • UInt32: カテゴリインデックス。

GC.Alloc

GC.Alloc は、ガベージコレクションの割り当てに対応するマーカーです。以下のデータが含まれます。

  • Int64: 割り当てのサイズ。
Video Profiler モジュール
ログファイル