ゲームラグ白書 › L1 クライアントのゲームプロセス
クライアントのガベージコレクション Client GC (Unity C#, Unreal, Lua)
原因ID cg-gc · 主担当 ゲーム開発チーム・クライアント開発
図と実験のあるメインページでこのカードを開く →
使い終わったメモリ(ガベージ)を回収する間、ゲーム全体が止まります。一定の間隔でカクつくのが特徴です。
なぜ 毎フレーム、一時的な文字列・配列・リストを作っては捨てる → すると ガベージがたまると、GCがメインスレッドを止めて回収 → 画面では 数秒〜数十秒ごとに規則的にカクつく
- 症状
- カクつき, フリーズ
- 要因
- ストール
- 誰に起きるか
- 自分だけ
- いつ
- 一定の周期で, 人が集中したとき
- 担当
- 主担当 ゲーム開発チーム・クライアント開発
- ゲーム開発チームの対応
- アロケーションの削減(文字列連結・LINQ・ラムダのキャプチャを避ける)、オブジェクトプール、インクリメンタルGCを有効のままにする(Unity 2020以降のデフォルト)、ロード画面のように止まっても問題ないタイミングで先にGCを実行。
- 数値の目安
- 通常は1回あたり数ms〜100ms、低スペックのスマホやメモリを多く使うゲームではそれ以上(実験では約150〜170ms)。UnityのGCは実行のたびにヒープ全体を調べるため、ゲームが使っているメモリが多いほど長くなります。
- グラフでは
- 周期的なスパイク · フレームタイム、GCの実行時刻
- 確認箇所
- 開発ビルドで、UnityプロファイラーのGC.Collect・GC.Allocマーカーを確認。Unrealはstat GCとstat Hitches(t.HitchFrameTimeThresholdで指定した時間を超えるフレームをログに記録)
- 該当する場合
- 跳ねたフレームごとにGC.Collectの区間があり、その長さが跳ねた長さとほぼ同じで、間隔が数秒〜数十秒と規則的。人が多い場所ではフレームあたりのGC.Allocが増える
- 該当しない場合
- 跳ねたフレームにGCの区間がなければ「メインスレッドでの同期ロード・シェーダーコンパイル」か「大人数の描画負荷」
- 確認手段
- ゲームサーバー・クライアントのログ・メトリクスが必要
- もっと詳しく
- UnityのようにC#を使うクライアントでよく起きます。戦闘ログの文字列、ダメージの数字、UIテキストを毎フレーム新しく作るコードが主な原因です。人が多い場所でだけカクつくなら、人数に比例してガベージが増えるコードがあるということです。インクリメンタルGCは1フレームに少しずつ(Unityのデフォルトは3ms)分けて回収しますが、回収する速度よりも速くガベージを生み出すと、結局一度にまとめて止まります。Unreal Engineにも使われなくなったゲームオブジェクトを片付ける独自のGCがあり、エンジンのバージョンや設定によって異なりますが、デフォルト設定では約1分ごとに実行され、1分間隔で一瞬止まる原因になることもあります。ゲームのルールをLuaのようなスクリプトで書いたクライアントでは、そのスクリプトのGCも別に動きます。
出典
- Garbage collection modes Unity
インクリメンタルGCがデフォルトで、複数フレームに分けて回収する。無効にするとヒープ全体を調べる間メインスレッドが止まり、数百msに達することもある - Scripting.GarbageCollector.CollectIncremental Unity
インクリメンタルGCが1回に使う時間(タイムスライス)のデフォルトの目標は3ms(incrementalTimeSliceNanoseconds) - Garbage Collection Settings in the Unreal Engine Project Settings Epic Games
UnrealのGCが決まった間隔(Time Between Purging Pending Kill Objects、秒単位)で実行されることを示す設定。デフォルト値の数字はこの文書には記載なし - Profiler markers reference Unity
GC.Collect:ガベージコレクション中にプログラムのコードが止まった区間(1ms未満〜数百ms)、GC.Alloc:マネージヒープへのアロケーション - Stat Commands in Unreal Engine Epic Games
stat GC(ガベージコレクションの統計)、stat Hitches(t.HitchFrameTimeThresholdを超えるフレームをログに記録)
あわせて読みたい原因
同じ層:L1 クライアントのゲームプロセス
同じ症状(カクつき)を起こすほかの層の原因
図と実験のあるメインページでこのカードを見る