Unreal Engine (UE) では、マーク & スイープ ガベージ コレクターを使用して UObject メモリを管理しています。 ソフト リアルタイム アプリケーションにとって、ガベージ コレクターは歴史的に 1 つの大きな欠点がありました。ガベージ コレクターがどのオブジェクトのメモリを解放できるかを決定する間、ゲームプレイでヒッチが発生する可能性を排除します。 UE では、このプロセスは 到達可能性分析 と呼ばれます。 UE は、ガベージ コレクションのこのフェーズが 1 フレーム内で完了することに依存しています。そのため、すべての UObject 処理 (特にゲームプレイ) が一時的に停止します。 到達可能性分析でスキャンする必要があるオブジェクトが多いほど、一時停止が長くなり、その結果として、目に見えるゲームプレイの処理落ちが発生する可能性があります。 プログラマーは、次のような方法で、いくつかの不具合を回避できます。
UObject のバジェットを厳しく抑える。
UObject プールを使用する。
通常のゲームプレイ中はガベージコレクションを無効にします。
ただし、これらの回避策は、コードの複雑さとプロジェクト全体のコストを増加させる傾向があります。
インクリメンタル到達可能性解析
UE では、インクリメンタル到達可能性解析を使用することで、これを改善します。 ユーザーは、ガベージ コレクターの到達可能性分析フェーズを、設定可能なフレームごとのソフト時間制限で、複数のフレームにわたって分割できるようになりました。 エンジンは、TObjectPtr プロパティを介して到達可能性のイテレーション間で UObject の参照をトラックします。 つまり、TObjectPtr に公開される UPROPERTY への割り当ては、ガベージ コレクションの進行中に直ちにそのオブジェクトを到達可能とマークします。 これはガベージ コレクターのライト バリアとしても知られています。
エンジンは、UObject や FGCObject AddReferencedObjects 関数を含む、ガベージ コレクターに UObject を公開する場所で、生の C++ ポインタではなく、TObjectPtr を使用するようにすでに変換されています。 Unreal Engineでビルドされたプロジェクトで増分到達可能性分析を使用するには、すべての UPROPERTY インスタンスを Raw C++ではなく TObjectPtr を使用するように変換することが重要です。変換しないと、ガベージコレクションが早すぎてUObjectsのメモリの一部が解放される可能性があります。 この機能は、まずは、実験的機能としてリリースされます。到達可能性解析フェーズが指定された制限時間を超える可能性があるためです。
インクリメンタル到達可能性解析を有効にする
インクリメンタル到達可能性解析は、プロジェクトの DefaultEngine.ini に以下のコンソール変数を追加することで、有効にすることができます。
[ConsoleVariables]
gc.AllowIncrementalReachability=1 ; enables Incremental Reachability Analysis
gc.AllowIncrementalGather=1 ; enables Incremental Gather Unreachable Objects
gc.IncrementalReachabilityTimeLimit=0.002 ; sets the soft time limit to 2ms追加のコンソール変数
コンソール変数は、ストレス テストとデバッグの目的で使用することもできます。
| コンソール変数 | 説明 | 型 |
|---|---|---|
| 指定したフレーム数だけ到達性解析を遅延させます。 GC バリアのストレス テストに使用します。 |
|
| 到達可能な (有効な) オブジェクトが到達不可能な (すぐに破壊される) オブジェクトを参照していないことを確認するために、到達可能性解析が完了した後にテストを実行します。 | 0:無効、1:有効 |
| 前のガベージ コレクションが完了した後、インクリメンタル ガベージ コレクションを再開し続けます。 | 0:無効、1:有効 |
パフォーマンス比較
以下は、インクリメンタル到達可能性をオフにしたサンプル プロジェクトのパフォーマンス グラフをUnreal Insights で可視化したものです。 青の線は総フレーム時間を表し、オレンジの線は到達可能性解析にかかった時間を表しています。 Unreal Insights は、複数のフレームで区切られた単一イベント間の連続グラフ線をプロットします。ガベージ コレクションがタイムライン全体を通して実行されているように見えても、実際には一度に 1 フレームしか実行されません。
次の比較グラフの最初の画像では、ガベージ コレクションが実行されるたびにスパイクが表示されます (タイムラインの一番上に GC ラベルで示されます)。
2 番目の画像では、インクリメンタル到達可能性がオンになっているため、GC のラグ スパイクがなくなり、インクリメンタル到達可能性が複数のフレームにまたがって分割されていることがわかります (幅が広くなった薄緑のバーで表されています)。
既知の制限事項
増分到達可能性は完全にスレッド セーフではありません。 状況により、ワーカー スレッドで操作されているオブジェクトは、ガベージ コレクターが UObject グラフをスキャンしている間、到達可能とマークされません。 その結果、オブジェクトが途中でガベージ コレクションされることがあります。 インクリメンタル到達可能性は、シングルスレッドビルド(専用サーバーなど)でのみ有効にすることをお勧めします。