# 低レベルのネイティブプラグインのプロファイリング

> Extend the profiler and collect performance data from native plug-ins.

低レベルのネイティブプラグインプロファイラー API を使用して、[プロファイラー](/engine/6000.0/manual/analysis/profiler/introduction.md) を拡張し、ネイティブプラグインコードのパフォーマンスデータを収集したり、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-reference

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

このプラグイン API は `IUnityProfiler.h` ヘッダーで宣言される `IUnityProfiler` インターフェースで表されます。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`      | プロファイラーから現在のスレッドの登録を解除します。                                                |

### IUnityProfiler の例##iunityprofiler-example

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

```lang-csharp
#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);

    // Code I want to see in Unity Profiler as "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 コールバック##iunityprofilercallbacks-api-callbacks

ネイティブ Profiler プラグイン API は、Unity のサブシステムとサードパーティ製のプロファイリング API 間のインターフェースを提供するため、外部プロファイリングツールを使用して Unity アプリケーションをプロファイルできます。`IUnityProfilerCallbacks` ヘッダーは API を公開し、Unity はこれを Unity インストールの `<UnityInstallPath>\Editor\Data\PluginAPI` フォルダーに保存します。(macOS の場合は、Unity アプリケーションを右クリックし、**Show Package Contents** を選択してください。ヘッダーは `Contents\PluginAPI` 内にあります)。

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

| **プロファイラー機能**    | **説明**                                                                                                                                                                                                                                                                                                                                        |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **カテゴリ**         | Unity はプロファイルデータをカテゴリ (レンダリング、スクリプティング、アニメーションなど) にグループ化し、各カテゴリに色を割り当てます。色分けされたカテゴリは、Profiler ウィンドウでデータの種類を視覚的に区別するのに役立ちます。Profiler ネイティブプラグイン API を使用すると、これらの色を取得して外部のプロファイリングツールで使用することができます。                                                                                                                                               |
| **Usage フラグ**    | usage フラグは、Unity が外部プロファイリングツールに送信するデータ量を減らすフィルターとして機能します。usage フラグを使うと、プロファイリングデータを外部ツールに送信する前に、不要な情報を削除することができます。Profiler は、以下の usage フラグをイベントマーカーに適用し、データをフィルタリングできるようにします。**Availability flags** マーカーが Unity エディターか、開発版プレイヤーか、リリース版プレイヤーで使用可能かを示すフラグ。**Verbosity levels** エディターで行っているタスクの種類とタスクが必要とする情報のレベル (例えば、内部、デバッグ、ユーザーレベル) に関連します。 |
| **フレームイベント**     | プロファイラーのネイティブプラグイン API を使用して、外部のプロファイリングツールでフレームタイムの解析を行うことができます。                                                                                                                                                                                                                                                                             |
| **スレッドプロファイリング** | Unity は著しい量の作業をスレッドで行います (例えば、メインスレッド、レンダースレッド、ジョブシステムワーカースレッドなど)。プロファイラーのネイティブプラグイン API を使用すると、どのスレッドでもプロファイリングを行うことができます。                                                                                                                                                                                                                   |

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

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

### IUnityProfilerCallbacks の例##iunityprofilercallbacks-example

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

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

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

```lang-csharp
#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 の例##unitysystraceplugin-example

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

```lang-csharp
| 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` を実行します。

## 特別なマーカー##special-markers

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

* `Profiler.DefaultMarker`
* `GC.Alloc`

### Profiler.DefaultMarker##profiler.defaultmarker

`Profiler.DefaultMarker` は、Unity が [Profiler.BeginSample](/engine/6000.0/script-reference/unity-engine-profiling/profiler/begin-sample.md) と [Profiler.EndSample](/engine/6000.0/script-reference/unity-engine-profiling/profiler/end-sample.md) のイベントのために予約しているマーカーです。

前の例では、`kUnityProfilerMarkerEventTypeBegin eventType` は `Profiler.BeginSample` イベントに対応し、以下のデータを持ちます。

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

### GC.Alloc##gc.alloc

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

* Int64: 割り当てのサイズ。

## 追加リソース##additional-resources

* [Profiler の基本](/engine/6000.0/manual/analysis/profiler/introduction.md)
* [コードへのプロファイリング情報の追加](/engine/6000.0/manual/analysis/profiler/adding-information-code.md)
* [ネイティブプラグインの基本](/engine/6000.0/manual/scripting/compilation-and-code-reload/plug-ins/native.md)
