はなちるのマイノート

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

【Unity】GarbageCollectorクラスでガベージコレクションのオンオフなどを制御する

ガベージコレクションを発生させないようにする

GarbageCollecor.GCModeを変更することによってガベージコレクションを発生させる・させない・手動で行うを選ぶことができます。

ただしWebGLとエディタ上ではサポートされていないことに注意してください。

// エディタ上で実行しようとすると以下のエラーが出る
InvalidOperationException: Setting garbage collector mode is not supported in the editor

public class Test : MonoBehaviour
{
    private void Start()
    {
        // ガベージコレクションを発生させないようにする
        GarbageCollector.GCMode = GarbageCollector.Mode.Disabled;
        
        // ガベージコレクションを発生させるようにする
        // GarbageCollector.GCMode = GarbageCollector.Mode.Enabled;
    }

    private void Update()
    {
        // Managed Heapに毎フレーム、メモリを確保する
        var array = new int[100];
    }
}

GarbageCollector.Mode.Disabledを設定すると、System.GC.Collect()を実行してもGCは働きません。

一応Standalone Macで計測してみた結果、メモリ使用量がどんどん増えていってはいました。

雑計測

GCModeの変更された時に処理を挟む

GarbageCollector.GCModeChangedを用いることで、GarbageCollector.GCModeが変更された際に処理を挟めます。

GarbageCollector.GCModeChanged += mode => Debug.Log(mode);

インクリメンタルガベージコレクションが有効かどうか調べる

// Incremental garbage collectionが有効化どうか
bool isIncremental = GarbageCollector.isIncremental;

GarbageCollector.isIncrementalPlayer Settingsで有効になっている かつ プラットフォームがサポートされている場合にtrueになります。

またインクリメンタルガベージコレクションが何者かについては、Unity公式ドキュメントに記載があります。

インクリメンタル ガベージコレクション (GC) は、ガベージコレクションの処理を複数のフレームに分散して行います。これは、Unity のデフォルトのガベージコレクションの動作です。
...
インクリメンタルモードでは、ガベージコレクションが全体的に速くなるわけではありませんが、ワークロードを複数のフレームに分散させるため、GC 関連のパフォーマンススパイクが減少します。このような中断は GC スパイク と呼ばれます。これは、Profiler ウィンドウ のフレームタイムグラフに大きなスパイクとして表示されるためです。

インクリメンタルガベージコレクション - Unity マニュアル

インクリメンタルガベージコレクションを手動実行する

// Incremental garbage collectionを手動実行する
// 返り値は追加のガベージコレクション作業が残っているかどうか
GarbageCollector.CollectIncremental(nanoseconds: 0UL);

ただしIncremental Garbage Collectionが有効でないと動作しません。(返り値は常にfalse)

インクリメンタルガベージコレクションの1Stepに制限時間を設ける

GarbageCollector.incrementalTimeSliceNanosecondsに時間を指定することで、インクリメンタルガベージコレクションの1ステップでの制限時間を指定できるそうです。

The target duration of a collection step when performing incremental garbage collection.

Scripting.GarbageCollector-incrementalTimeSliceNanoseconds - Unity スクリプトリファレンス