【Unity】UnityのProfilerでそのフレームにおけるメモリ割り当てを分析する

UnityのProfilerでそのフレームにおけるメモリ割り当てを分析する方法です。

Unity2018.4.0

手順

まずProfilerでメモリ割り当てを見る手順をまとめます。
最初にWindow > Analysis > ProfilerからProfilerを開きます。

f:id:halya_11:20190714172856p:plain

Profilerを開いたら、ProfilerのRecordボタンを押してUnityを再生します。
CPU Usageのグラフ部分をクリックするとそのFrameにおける処理負荷がHierarchyに表示されます。

f:id:halya_11:20190526220221p:plain

GC Alloc列に入っている値がそのフレームで割り当てられたメモリ量です。

f:id:halya_11:20190714174421p:plain

列のタイトル(GC Alloc)をクリックすると降順に並べ替えられます。
基本的な手順は以上です。

使ってみる

それでは実際にスクリプトを書いてProfilerで計測してみます。
まず、以下のようにint型のローカル変数をUpdate()内で使ってみます。

using UnityEngine;

public class Example : MonoBehaviour
{
    void Update()
    {
        var a = 1;
        var b = 2;
        var c = a + b;
    }
}

値型のローカル変数はヒープではなくスタックに乗るので、アロケーションは発生しないはずです。
これをProfilerで見てみます。

f:id:halya_11:20190714174809p:plain

GC Allocがすべて0Bになっていることが確認できました。
次にスクリプトのint型をstring型に変更してみます。

using UnityEngine;

public class Example : MonoBehaviour
{
    void Update()
    {
        var a = "a";
        var b = "b";
        var c = a + b;
    }
}

これをProfilerで見てみます。

f:id:halya_11:20190714175203p:plain

30Bのメモリ割り当てが発生していることが確認できました。

細かく見たい場合はDeep Profiling

ただこの状態ではどのメソッドで割り当てが起きているか正確にはわかりません。
より詳しく処理負荷の要因を探るにはDeep Profileを有効にします。

f:id:halya_11:20190526220313p:plain

これにより、割り当てを発生させているメソッドを正確に特定できました。

f:id:halya_11:20190714180058p:plain

メインスレッド以外はプロファイリングできない(Unity2019.2までは)

Profilerによるメモリ割り当ての分析はメインスレッドに対してのみ有効です。
メインスレッド以外の割り当てを分析したい場合、処理を一時的にメインスレッドに移すか、
Profiling.Profiler.BeginThreadProfilingを使ってProfilerに処理負荷が表示されるようにする必要があります。

docs.unity3d.com

ちなみにUnity2019.3からはメインスレッド以外も分析できるようになるらしいです。

計測はビルド後に行うべき

Unityの内部的なAPIでは、UnityEditorで再生する場合とビルド後に再生する場合でメモリの割り当ての仕方が異なる場合があります。

代表的なものはGetComponent()で、これはUnityEditorで再生するとメモリ割り当てが発生しますが、
ビルド後に再生した場合はメモリ割り当てが発生しないようです。

参考

docs.unity3d.com

docs.unity3d.com