コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】static 変数、Hierarchy のオブジェクト、プレハブ、ScriptableObject などがどのくらいヒープ領域を使用しているか内訳を見ることができる「Unity Heap Crawler」紹介

はじめに

「Unity Heap Crawler」を Unity プロジェクトに導入することで
static 変数、Hierarchy のオブジェクト、プレハブ、ScriptableObject などが
どのくらいヒープ領域を使用しているか内訳を見ることができます

使い方

f:id:baba_s:20190326141958p:plain

Unity エディタ再生中にメニューの
「Tools > Memory > Default Heap Snapshot」を選択します

すると Unity プロジェクトのフォルダに「snapshot-XXXX」フォルダが作成され、
その中にメモリ使用量の内訳がテキストファイルで出力されます

使用例

using System.Linq;
using UnityEngine;

public class Example : MonoBehaviour
{
    public class Pokemon
    {
        public string m_name = "ピカチュウ";
    }

    public static Pokemon[] m_pokemons = Enumerable
        .Range( 0, 1000000 )
        .Select( c => new Pokemon() )
        .ToArray()
    ;
}

例えば static 変数で Pokemon というクラスの配列を定義して、
1,000,000 個の要素を作成した状態で「Unity Heap Crawler」を実行して、
出力された「2-static-fields.txt」を開いてみると、

Example.m_pokemons [Pokemon[]] 30.5 MB ★
Keywords.keywords [LookupTable] 545.5 KB
  root [Node] 545.4 KB
UIElementsUtility.s_UIElementsCache [Dictionary`2<Int32, Panel>] 380.1 KB
  entries [Entry[]] 379.2 KB
...

このように m_pokemons 配列が 30.5 MB 使用していることがわかります

補足1

using System.Linq;
using UnityEngine;

public class Example : MonoBehaviour
{
    public struct Pokemon
    {
        public string m_name;

        public Pokemon( string name )
        {
            m_name = name;
        }
    }

    public static Pokemon[] m_pokemons = Enumerable
        .Range( 0, 1000000 )
        .Select( c => new Pokemon( "ピカチュウ" ) )
        .ToArray()
    ;
}

クラスではなく構造体の場合は

Example.m_pokemons [Pokemon[]] 7.63 MB ★
Keywords.keywords [LookupTable] 545.5 KB
  root [Node] 545.4 KB
UIElementsUtility.s_UIElementsCache [Dictionary`2<Int32, Panel>] 378.7 KB
  entries [Entry[]] 377.8 KB

...

メモリ使用量が減ります

補足2

using System.Linq;
using UnityEngine;

public class Example : MonoBehaviour
{
    public class Pokemon
    {
        public byte[] m_name;
    }

    public static Pokemon[] m_pokemons;

    private void Awake()
    {
        var name = GZipCompressor.Compress( "ピカチュウ" );

        m_pokemons = Enumerable
            .Range( 0, 1000000 )
            .Select( c => new Pokemon { m_name = name } )
            .ToArray()
        ;
    }
}

gzip を使用して圧縮した byte[] を所持している場合は

Example.m_pokemons [Pokemon[]] 30.5 MB ★
Keywords.keywords [LookupTable] 545.5 KB
  root [Node] 545.4 KB
UIElementsUtility.s_UIElementsCache [Dictionary`2<Int32, Panel>] 381.1 KB
  entries [Entry[]] 380.2 KB

string を使用した時とメモリ使用量は変わりませんでした

関連記事