はじめに
今回はGarbageCollector
クラスを用いてガベージコレクションのオン・オフなどを制御してみようという記事になります。
docs.unity3d.com
ガベージコレクションを発生させないようにする
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.isIncremental
はPlayer Settings
で有効になっている かつ プラットフォームがサポートされている場合にtrue
になります。
またインクリメンタルガベージコレクションが何者かについては、Unity公式ドキュメントに記載があります。
インクリメンタル ガベージコレクション (GC) は、ガベージコレクションの処理を複数のフレームに分散して行います。これは、Unity のデフォルトのガベージコレクションの動作です。
...
インクリメンタルモードでは、ガベージコレクションが全体的に速くなるわけではありませんが、ワークロードを複数のフレームに分散させるため、GC 関連のパフォーマンススパイクが減少します。このような中断は GC スパイク と呼ばれます。これは、Profiler ウィンドウ のフレームタイムグラフに大きなスパイクとして表示されるためです。
インクリメンタルガベージコレクションを手動実行する
// 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 スクリプトリファレンス