はなちるのマイノート

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

【Unity】UnityTestFramework上でパフォーマンス測定ができるPerformance Testing Packageの基礎的な使い方

はじめに

今回はPerformance Testing PackageというUnity Test Framework向けのパフォーマンス計測機能を提供するパッケージを紹介したいと思います。

The Unity Performance Testing Package extends Unity Test Framework with performance testing capabilities. It provides an API and test case decorators for taking measurements/samples of Unity profiler markers, and other custom metrics, in the Unity Editor and built players. It also collects configuration metadata that is useful for comparing data across different hardware and configurations, such as build and player settings.

// DeepL翻訳
Unity Performance Testing PackageはUnity Test Frameworkをパフォーマンステスト機能で拡張します。これは、Unityエディタとビルドされたプレイヤーで、Unityプロファイラマーカーやその他のカスタムメトリクスの測定/サンプルを取得するためのAPIとテストケースデコレータを提供します。また、ビルドやプレーヤーの設定など、異なるハードウェアや設定間でデータを比較するのに便利な設定メタデータも収集します。

実際に利用している例

インストール方法

Package Managerを開き、Add pacakge from git URL...よりcom.unity.test-framework.performanceと入力します。

com.unity.test-framework.performanceと入力する
Performance testing APIをインストール

ただしUnityのバージョンによってはPerformance Testing Packageのバージョンが指定されている場合はあります。少なくともUnity 2020.3以降は最新のv3.0.3を利用できるようですが、Unity 2019.4では互換性の問題から2.8.1-previewを利用するとのことです。
Performance Testing Package for Unity Test Framework | Performance testing API | 3.0.3

基礎的な使い方

Meature.Method

Meature.Methodを利用することでパフォーマンスを測定できます。

[Test, Performance]
public void Test()
{
    Measure.Method(() =>
        {
            Debug.Log("計測したい処理");
        })
        .Run();
}

[Test][UnityTest]と一緒に[Performance]をつけることでパフォーマンス計測の対象だとマークをつけます。パフォーマンス計測したい処理をMeasure.Methodの引数に渡し、Run()で実行を行います。

またメソッドチェーンにて以下の機能を追加することができます。

  • WarmupCount(int n) : 測定前に処理を実行する回数。
  • MeasurementCount(int n) : 計測する回数。デフォルトは9回。
  • DynamicMeasurementCount(OutlierMode outlierMode) : サンプルの誤差に基づいて動的に適切な測定回数を実行します。
  • DynamicMeasurementCount(double maxRelativeError, ConfidenceLevel confidenceLevel, OutlierMode outlierMode) : 上記のおオーバーロード。
  • IterationsPerMeasurement(int n) : 測定ごとの処理の実行回数。
  • SampleGroup(string name) : 測定の名前。デフォルトはTime
  • SampleGroup(SampleGroup sampleGroup) : 上記のオーバーロード。
  • GC() : ガベージコレクションの割り当て呼び出し総数を測定します。
  • SetUp(Action action) : メソッド実行の前に反復ごとに呼び出されます。測定はされません。
  • CleanUp(Action action) : メソッド実行の前に反復ごとに呼び出されます。測定はされません。
[Test, Performance]
public void Test()
{
    Measure.Method(() =>
        {
            Debug.Log("計測したい処理");
        })
        .WarmupCount(10)
        .MeasurementCount(10)
        .IterationsPerMeasurement(5)
        .GC()
        .SetUp(() =>
        {
            Debug.Log("SetUp");
        })
        .CleanUp(() =>
        {
            Debug.Log("CleanUp");
        })
        .Run();
}
Window > General > Performance Test Report

サンプル

Measure.Methodを利用してJsonUtilitySystem.Text.Jsonのパフォーマンス比較するサンプルを載せます。

[Serializable]
public class Person
{
    [JsonInclude] public int age;
    [JsonInclude] public string name;
}

[JsonSerializable(typeof(Person))]
public partial class PersonContext : JsonSerializerContext{}

public class SampleTest
{
    private const int Count = 1000;
    
    [Test, Performance]
    public void Serialize_SystemTextJson()
    {
        var person = new Person
        {
            age = 20,
            name = "john"
        };

        Measure.Method(() =>
            {
                _ = JsonSerializer.Serialize(person);
            })
            .WarmupCount(1)
            .MeasurementCount(Count)
            .Run();
    }
    
    [Test, Performance]
    public void Serialize_SystemTextJson_SourceGenerator()
    {
        var person = new Person
        {
            age = 20,
            name = "john"
        };

        Measure.Method(() =>
            {
                _ = JsonSerializer.Serialize(person, PersonContext.Default.Person);
            })
            .WarmupCount(1)
            .MeasurementCount(Count)
            .Run();
    }
    
    [Test, Performance]
    public void Serialize_JsonUtility()
    {
        var person = new Person
        {
            age = 20,
            name = "john"
        };
        
        Measure.Method(() =>
            {
                _ = JsonUtility.ToJson(person);
            })
            .WarmupCount(1)
            .MeasurementCount(Count)
            .Run();
    }
}

WarmupCountメソッドを利用することで、最初に指定した回数だけパフォーマンスを計測せずに実行を行います。またIterationsPerMeasurementメソッドは1回の測定におけるメソッドの実行回数を指定します。

メニューバーのWindow > Analysis > Performance Test Reportよりパフォーマンス計測結果をみることができます。

Performance Test Report

表示されているTest Viewの文字列の意味は以下の通りです。

  • Name : テストの名前
  • Groups : グループの数
  • Deviation : 標準偏差を中央値で割ったもの
  • SD : 標準偏差(平均からの隔たりの大きさの平均値)
  • Median : 中央値
  • Min : 最小値
  • Max : 最大値

さいごに

Measure.Frames, Measure.Scope, Measure.ProfileMarkers, Measure.CustomなどのMeasure.Method以外の測定方法もあります。PlayModeで利用する場合やコルーチンなどで測定する場合はこれらを利用する必要があります。

詳細は公式ドキュメントを参照してください。