はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Unity】Profiler.BeginSampleとProfiler.EndSampleを用いてコードの一部をプロファイリングする

はじめに

今回はProfilerクラスのメソッドであるBeginSampleEndSampleについて紹介したいと思います。

概要

まずは公式ドキュメントの説明を載せます。

// Profiler.BeginSample
カスタムラベルの付いたコードの一部のプロファイリングを開始します

Profiling.Profiler-BeginSample - Unity スクリプトリファレンス

// Profiler.EndSample
カスタムラベルの付いたコードの一部のプロファイリングを終了します

これは Profiler ヒエラルキーに表示されます。

Profiling.Profiler-EndSample - Unity スクリプトリファレンス

もうすこし分かりやすくすると、Profiler.BeginSampleProfiler.EndSampleで囲ったコードのプロファイルをProfilerで確認できるようになります。

具体的には1フレームでの呼び出し回数やGC.Alloc、処理時間などを知る事ができます。

private void Update()
{
    Profiler.BeginSample(name: "Sample Profile");
        
    // プロファイリングしたい処理
    _ = Enumerable.Range(0, 1000000).ToArray();
        
    Profiler.EndSample();
}
ProfilerのHierarchyにて確認できる

補足

Profiler.BeginSampleの公式ドキュメントの説明によると、Build後はコードが含まれないようになっているそうです。

Profiler.BeginSample is conditionally compiled away using ConditionalAttribute. Thus it will have zero overhead, when it is deployed in non-Development Build.

内部実装を見てみると確かに[Conditional]がついていますね。

/// <summary>
///   <para>Begin profiling a piece of code with a custom label.</para>
/// </summary>
/// <param name="name">A string to identify the sample in the Profiler window.</param>
/// <param name="targetObject">An object that provides context to the sample,.</param>
[Conditional("ENABLE_PROFILER")]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void BeginSample(string name)
{
    Profiler.ValidateArguments(name);
    Profiler.BeginSampleImpl(name, (UnityEngine.Object) null);
}

/// <summary>
///   <para>Begin profiling a piece of code with a custom label.</para>
/// </summary>
/// <param name="name">A string to identify the sample in the Profiler window.</param>
/// <param name="targetObject">An object that provides context to the sample,.</param>
[Conditional("ENABLE_PROFILER")]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void BeginSample(string name, UnityEngine.Object targetObject)
{
    Profiler.ValidateArguments(name);
    Profiler.BeginSampleImpl(name, targetObject);
}

...

/// <summary>
///   <para>Ends the current profiling sample.</para>
/// </summary>
[Conditional("ENABLE_PROFILER")]
[NativeMethod(IsFreeFunction = true, IsThreadSafe = true, Name = "ProfilerBindings::EndSample")]
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern void EndSample();

ありがたいです。