# 로우레벨 네이티브 플러그인 프로파일링

> 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와 같은 타사 프로파일링 툴로 전송할 수 있습니다.

로우레벨 네이티브 플러그인 프로파일러 API는 Unity 프로파일러와 외부 툴링 간 커뮤니케이션을 위해 다음과 같은 인터페이스를 제공합니다.

* **IUnityProfiler**: 이 인터페이스를 사용하여 C/C++ 네이티브 플러그인 코드에서 Unity 프로파일러에 계측 이벤트를 추가합니다.
* **IUnityProfilerCallbacks**: 이 인터페이스를 사용하여 Unity 프로파일러 이벤트를 인터셉트해서 저장하거나 다른 툴로 리디렉션합니다.

## 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

이 예시는 프로파일러 창에 표시되는 프로파일러 이벤트를 생성합니다.

```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

네이티브 프로파일러 플러그인 API는 Unity 보조 시스템과 타사 프로파일링 API 간의 인터페이스를 제공하므로 외부 프로파일링 툴을 사용하여 Unity 애플리케이션을 프로파일링할 수 있습니다. `IUnityProfilerCallbacks` 헤더는 설치된 Unity의 `<UnityInstallPath>\Editor\Data\PluginAPI` 폴더에 저장되는 API를 표시합니다. macOS에서는 Unity 애플리케이션을 오른쪽 클릭한 후 **Show Package Contents**를 선택합니다. 헤더는 `Contents\PluginAPI`에 있습니다.

다음 Unity 프로파일러 기능을 사용하면 애플리케이션의 성능을 분석하는 데 도움이 되는 계측 데이터를 캡처할 수 있습니다.

| **프로파일러 기능**  | **설명**                                                                                                                                                                                                                                                                                                         |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **카테고리**      | Unity는 프로파일 데이터를 카테고리(예: Rendering, Scripting, Animation)로 그룹화하고 각 카테고리에 컬러를 할당합니다. 컬러로 코딩된 카테고리를 사용하면 프로파일러 창의 데이터 유형을 시각적으로 구분할 수 있습니다. 프로파일러 네이티브 플러그인 API는 외부 프로파일링 툴에서 이러한 컬러를 사용할 수 있도록 가져옵니다.                                                                                                           |
| **사용 플래그**    | Unity가 외부 프로파일링 툴로 전송하는 데이터 양을 줄이는 필터 역할을 합니다. 사용 플래그를 사용하면 Unity가 외부 툴로 전송하기 전에 프로파일링 데이터에서 불필요한 정보를 제거할 수 있습니다. 프로파일러는 효과적인 데이터 필터링을 위해 다음의 사용 플래그를 이벤트 마커에 적용합니다.**유효성 플래그**: Unity 에디터나 개발 또는 릴리스 플레이어에서 마커의 이용 가능 여부를 설명합니다.**상세도 수준**: 에디터에서 수행하는 작업 유형 및 작업에 필요한 정보 레벨(예: 내부, 디버그 또는 사용자 레벨)과 관련이 있습니다. |
| **프레임 이벤트**   | 프로파일러 네이티브 플러그인 API를 사용하면 외부 프로파일링 툴에서 프레임 시간 분석을 수행할 수 있습니다.                                                                                                                                                                                                                                                  |
| **스레드 프로파일링** | Unity는 스레드(예: 메인 스레드, 렌더 스레드 및 잡 시스템 워커 스레드)에 대해 상당한 양의 작업을 수행합니다. 프로파일러 네이티브 플러그인 API를 사용하면 모든 스레드에 대한 프로파일링을 활성화할 수 있습니다.                                                                                                                                                                                    |

Unity 프로파일러가 외부 프로파일러에서 생성하는 계측 데이터를 사용하려면 타사 프로파일러를 통합하는 C/C++ 플러그인 코드에서 다음의 최소 콜백 집합을 사용하십시오.

| **콜백**                           | **기능**                                                                                                                                                                                                                                                    |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `RegisterCreateCategoryCallback` | `IUnityProfilerCreateCategoryCallback` 콜백을 등록하여 Unity가 카테고리를 생성할 때마다 프로파일러 카테고리 이름과 컬러를 가져옵니다.                                                                                                                                                            |
| `RegisterCreateMarkerCallback`   | Unity가 마커를 생성할 때마다 호출되는 `IUnityProfilerCreateMarkerCallback` 콜백을 등록합니다. 이를 사용하여 마커의 이름, 프로파일러 카테고리, 사용 플래그를 가져옵니다. 콜백 함수의 const `UnityProfilerMarkerDesc* markerDesc` 파라미터는 `RegisterMarkerEventCallback`에서 마커를 필터링하는 데 사용할 수 있는 마커 설명에 대한 영구 포인터를 나타냅니다. |
| `RegisterMarkerEventCallback`    | Unity가 싱글샷, 범위 지정, 메모리 할당 또는 가비지 컬렉션 이벤트가 발생할 때 호출하는 IUnityProfilerMarkerEventCallback 콜백을 등록합니다. 그런 다음 이 콜백을 사용하여 외부 프로파일링 툴에서 관련 함수를 호출할 수 있습니다. **참고:** Unity는 `GC.Alloc` 마커로 메모리 할당 이벤트를 나타내고, `GC.Collect` 마커로 가비지 컬렉션 이벤트를 나타냅니다.                   |
| `RegisterFrameCallback`          | 프레임을 사용하지 않는 외부 프로파일링 툴이 이러한 샘플을 사용할 수 있도록 샘플을 논리 프레임으로 캡슐화합니다. 또한 Unity가 다음 논리적 CPU 프레임을 시작할 때 Unity 프로파일러가 실행하는 콜백을 등록합니다.                                                                                                                              |
| `RegisterCreateThreadCallback`   | Unity가 프로파일링을 위해 스레드를 등록할 때마다 내부 스레드 이름을 가져오는 콜백을 등록합니다.                                                                                                                                                                                                  |

### IUnityProfilerCallbacks 예시##iunityprofilercallbacks-example

이 예제는 푸시/표시 시맨틱이 있는 다른 프로파일러에 Unity 프로파일러 이벤트를 전달하는 방법을 보여 줍니다. 다음의 두 가지 함수를 제공합니다.

* `void MyProfilerPushMarker(const char* name)`: 명명된 마커를 푸시합니다.
* `void MyProfilerPopMarker()`: 계측 마커를 표시합니다.

다음 예제는 Unity 프로파일러에서 외부 프로파일러로 계측 시작 및 종료 이벤트를 전달하는 데 필요한 최소한의 구현을 제공합니다.

```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

프레임마다 한 번 마커 콜백을 동적으로 등록하거나 등록 해제할 수 있습니다. 다음 예제는 타사 프로파일 상태에 따라 콜백을 활성화하거나 비활성화하여 프로파일링 오버헤드를 최소화합니다.

```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 배열: `Profiler.BeginSample`에 전달되는 UTF16 문자열입니다. 크기는 바이트 단위입니다.
* UInt32: 카테고리 인덱스입니다.

### GC.Alloc##gc.alloc

`GC.Alloc`은 가비지 컬렉션 할당에 해당하는 마커입니다. 다음의 데이터를 포함합니다.

* Int64: 할당 크기입니다.

## 추가 리소스##additional-resources

* [프로파일러 소개](/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)
