Version: Unity 6.0 (6000.0)
言語 : 日本語
ガーベジコレクターの概要
ガベージコレクションを無効にする

インクリメンタルガベージコレクション

インクリメンタルガベージコレクション (GC) は、ガベージコレクションの処理を複数のフレームに分散して行います。これは、Unity のデフォルトのガベージコレクションの動作です。

インクリメンタルガベージコレクションを有効にするには、Player Settings を開き、Use incremental GC を有効にします。これはデフォルトで有効になっています。
インクリメンタルガベージコレクションを有効にするには、Player Settings を開き、Use incremental GC を有効にします。これはデフォルトで有効になっています。

Unity のガベージコレクターは、Boehm–Demers–Weiser ガベージコレクターを使用しています。デフォルトで、Unity は増分モードで使用します。つまり、ガベージコレクターは、メインの CPU スレッドを停止する (stop-the-world garbage collection) 代わりに、複数のフレームにわたって作業量を分割して、マネージヒープのすべてのオブジェクトを処理します。これは、ガベージコレクターがマネージヒープのオブジェクトを処理するための中断を 1 回に長く行うのではなく、実行中のアプリケーションの中断をより短くすることを意味します。

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

増分モード (メニューで Edit > Project Settings > Player > Other Settings > Configuration > Use Incremental GC を選択) を無効にする場合、ガベージコレクターはコレクションパスを実行する際にヒープ全体を調べる必要があります。これは、ガベージコレクターが実行されるたびに、メインの CPU スレッドを停止するため、stop-the-world ガベージコレクションとして知られています。マネージヒープのすべてのオブジェクトを処理した後にのみ実行が再開されるため、アプリケーションのパフォーマンスに影響を与える GC スパイクを発生させる可能性があります。また、ガベージコレクターは非圧縮型です。つまり、Unity はオブジェクト間のギャップを埋めるためにメモリ内のオブジェクトを再分配しません。

重要:Web プラットフォームは、インクリメンタルガベージコレクションをサポートしていません。

インクリメンタルガベージコレクションが無効になっている場合、ガベージコレクションを実行するために Unity がプログラムコードの実行を停止すると、GC スパイクが発生します。この遅延は、ガベージコレクターが処理する必要のある割り当ての数や、アプリケーションが実行されているプラットフォームに応じて、数百ミリ秒続くことがあります。

これは、ゲームなどのリアルタイムアプリケーションでは問題となります。ガベージコレクターがアプリケーションの実行を中断すると、スムーズなアニメーションに必要な一定のフレームレートを維持することが難しくなるからです。

インクリメンタルガベージコレクションの例

以下のプロファイラーのスクリーンショットは、インクリメンタルガベージコレクションがフレームレートの問題を軽減することを示しています。

インクリメンタル GC を有効にしたプロファイリングセッション
インクリメンタル GC を有効にしたプロファイリングセッション
インクリメンタル GC を無効にしたプロファイリングセッション
インクリメンタル GC を無効にしたプロファイリングセッション

上のプロファイリングセッションでは、インクリメンタル GC が有効になっています。アプリケーションは一貫してフレームレートを 60 fps に維持しています。これは、ガベージコレクターがガベージコレクション操作を複数のフレームに分散させ、各フレームの小さなタイムスライス (黄色の VSync のすぐ上にある暗い緑色の部分) を使用しているためです。

下のプロファイリングセッションでは、インクリメンタル GC が無効になっていますが、明らかに GC スパイクが見られます。このスパイクにより 60 fps の滑らかなフレームレートが中断され、ガベージコレクションが発生するフレームが、60 fps を維持するために必要な 16 MS の制限を超えています。

アプリケーションが VSync または Application.targetFrameRate を使用する場合、Unity はガベージコレクションに割り当てる時間を、利用可能な残りのフレーム時間に基づいて調整します。このようにすることで、Unity は、本来ならば待機する時間にガベージコレクションを実行することが可能になり、パフォーマンスへの影響を最小限に抑えることができます。

注意(プロジェクトの Quality settings または Application.VSync プロパティで) VSync CountDon’t Sync 以外に設定した場合、または Application.targetFrameRate プロパティを有効にした場合は、フレームの終わりに残っている何にも使用されていない時間が、インクリメンタルガベージコレクションに自動的に使用されます。

インクリメンタルガベージコレクションの動作をより正確に制御するには、Scripting.GarbageCollector クラスを使用します。例えば、VSync やターゲットフレームレートを使用したくない場合、フレーム終了までの時間を自身で計算し、その時間をガベージコレクターに入力して使用することができます。

インクリメンタルガベージコレクションを無効にする

インクリメンタルガベージコレクションは、アプリケーションにとって問題となる場合があります。ガベージコレクターがこのモードで作業を分割する際に、マーキングフェーズも分割されるためです。マーキングフェーズとは、ガベージコレクターがすべてのマネージオブジェクトをスキャンし、どのオブジェクトがまだ使用されているか、どのオブジェクトをクリーンアップできるかを判断するフェーズです。

マーキングフェーズの分割は、オブジェクト間の参照のほとんどが作業スライスの間で変更されない場合にはうまくいきます。しかし、オブジェクトの参照が変更されると、ガベージコレクターは次のイテレーションでそれらのオブジェクトを再度スキャンしなければなりません。つまり、あまりにも多くの変更が行われるとインクリメンタルガベージコレクターに負荷を与える可能性があり、常に多くの仕事があるため、マーキングフェーズが決して終了しない状況を作り出すことを意味します。このような状況が発生すると、ガベージコレクターは、完全な、非増分コレクションを行うようにフォールバックします。

Unity がインクリメンタルガベージコレクションを使用する場合、参照が変更されるたびにガベージコレクターに通知するための追加コード (ライトバリアと呼ばれます) を生成し、オブジェクトの再スキャンが必要かどうかを認識できるようにします。これにより、参照を変更する際にオーバーヘッドが発生し、一部のマネージコードではパフォーマンスへの影響があります。

インクリメンタルガベージコレクションを無効にするには、Player Settings ウィンドウ (Edit > Project Settings > Player > Configuration を選択) を開いて、Use Incremental GC を無効にします。ほとんどの Unity プロジェクト、特にガベージコレクションのスパイクが問題となっているプロジェクトでは、インクリメンタルガベージコレクションのメリットが得られますが、プロファイラーを使用して、アプリケーションが期待どおりに動作することを常に確認する必要があります。

ガーベジコレクターの概要
ガベージコレクションを無効にする