한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

Game-Lag-Whitepaper › L1 Spielprozess auf dem Client

Garbage Collection auf dem Client Client GC (Unity C#, Unreal, Lua)

Ursachen-ID cg-gc · Hauptzuständig Client-Entwicklung (Entwicklungsteam)

In der interaktiven Fassung mit Grafiken und Experimenten öffnen →

Während nicht mehr benötigter Speicher (Garbage) freigegeben wird, steht das ganze Spiel still. Typisch ist Ruckeln in regelmäßigen Abständen.

Warum In jedem Frame entstehen temporäre Strings, Arrays und Listen, die gleich wieder verworfen werden → Folge Hat sich genug Garbage angesammelt, hält die GC den Main-Thread an und räumt auf → Auf dem Bildschirm Regelmäßiges Ruckeln alle paar Sekunden bis alle paar Dutzend Sekunden

Symptome
Ruckeln, Freeze
Faktoren
Stillstand
Wer ist betroffen
Nur ich
Wann
In festen Abständen, Bei großem Andrang
Zuständigkeit
Hauptzuständig Client-Entwicklung (Entwicklungsteam)
Aufgaben Entwicklungsteam
Allokationen reduzieren (String-Verkettung, LINQ und Lambda-Captures vermeiden), Object-Pools nutzen, inkrementelle GC eingeschaltet lassen (seit Unity 2020 Standard), die GC vorab dann auslösen, wenn ein Stillstand nicht stört, etwa auf Ladebildschirmen.
Größenordnungen
Meist einige ms bis 100 ms pro Lauf, auf schwachen Smartphones oder bei Spielen mit hohem Speicherbedarf mehr (im Experiment etwa 150–170 ms). Die GC von Unity durchsucht bei jedem Lauf den gesamten Heap. Je mehr Speicher das Spiel belegt, desto länger dauert sie.
Im Graphen
Spitzen in festen Abständen · Frametime, Zeitpunkte der GC-Läufe
Wo nachsehen
In einem Development-Build die Marker GC.Collect und GC.Alloc im Unity Profiler ansehen. In Unreal stat GC und stat Hitches (protokolliert Frames, die länger als der mit t.HitchFrameTimeThreshold festgelegte Wert dauern)
Spricht dafür
Jeder Ausreißer-Frame enthält einen GC.Collect-Abschnitt von etwa der Länge des Ausschlags, die Abstände sind regelmäßig und liegen bei einigen bis einigen Dutzend Sekunden. An belebten Orten steigt GC.Alloc pro Frame
Spricht dagegen
Kein GC-Abschnitt im Ausreißer-Frame: „Synchrones Laden und Shader-Kompilierung im Main-Thread“ oder „Renderlast durch große Spielermengen“
Prüfmittel
Logs oder Metriken aus Spielserver bzw. Client nötig
Mehr dazu
Häufig bei Clients mit C#, etwa in Unity. Hauptverursacher ist Code, der Kampflog-Texte, Schadenszahlen und UI-Texte in jedem Frame neu erzeugt. Ruckelt es nur an belebten Orten, gibt es Code, dessen Garbage mit der Spielerzahl wächst. Die inkrementelle GC sammelt pro Frame nur ein Stück (Unity-Standard 3 ms). Entsteht Garbage schneller, als gesammelt wird, steht das Spiel am Ende trotzdem auf einen Schlag still. Auch die Unreal Engine hat eine eigene GC, die nicht mehr genutzte Spielobjekte aufräumt. Abhängig von Engine-Version und Einstellungen läuft sie in der Standardkonfiguration etwa einmal pro Minute und kann so ein Stocken im Minutentakt verursachen. Clients, deren Spielregeln in einer Skriptsprache wie Lua geschrieben sind, haben zusätzlich die eigene GC dieser Skriptsprache.

Quellen

  1. Garbage collection modes Unity
    Inkrementelle GC ist Standard und sammelt verteilt über mehrere Frames. Ohne sie steht der Main-Thread still, während der gesamte Heap durchsucht wird, im Extremfall mehrere hundert ms
  2. Scripting.GarbageCollector.CollectIncremental Unity
    Standardziel für die Zeit, die die inkrementelle GC pro Durchgang nutzt (Zeitscheibe): 3 ms (incrementalTimeSliceNanoseconds)
  3. Garbage Collection Settings in the Unreal Engine Project Settings Epic Games
    Einstellung, nach der die Unreal-GC in festen Abständen läuft (Time Between Purging Pending Kill Objects, in Sekunden). Den Standardwert nennt dieses Dokument nicht
  4. Profiler markers reference Unity
    GC.Collect: Abschnitt, in dem der Programmcode während der Garbage Collection angehalten ist (unter 1 ms bis mehrere hundert ms), GC.Alloc: Allokation im Managed Heap
  5. Stat Commands in Unreal Engine Epic Games
    stat GC (Statistik zur Garbage Collection), stat Hitches (protokolliert Frames über t.HitchFrameTimeThreshold)

Verwandte Ursachen

Gleiche Schicht: L1 Spielprozess auf dem Client

Ursachen aus anderen Schichten mit demselben Symptom (Ruckeln)

Karte in der interaktiven Fassung mit Grafiken und Experimenten ansehen