When live data gets close to the heap limit, each GC reclaims almost nothing, so GC runs over and over without a break.
Why An event crowd or a leak pushes live data close to the heap limit → Effect GC reclaims only a little, so another full GC follows right away and GC uses most of the CPU → On screen The whole server alternates between slow motion and freezes for several minutes, then dies from running out of memory
Evening peak hours, When crowds gather, The longer it runs
Owner
Primary owner Game team (Server development) · Also Infra team (Server infrastructure)
Game team action items
Size the heap well above peak live data (usually 2× or more), reduce long-held references and leaks.
Infra team action items
Alert on GC time ratio, restart promptly without waiting for it to recover, use instances with enough memory to grow the heap.
Ballpark numbers
GC taking more than 10% of run time is usually treated as a warning sign. Some Java GCs throw an out-of-memory error when they spend 98% of the time in GC and still reclaim almost nothing.
On the graph
Hits a ceiling · Heap after GC, GC time ratio
Where to look
How close the heap left after GC is to the max heap, and the share of time spent in GC. Java: “after GC (heap size)” in -Xlog:gc lines and how often Pause Full lines appear. .NET: dotnet-counters (% Time in GC since last GC on .NET 8 and earlier, growth of dotnet.gc.pause.time on .NET 9 and later). Go: the interval between GODEBUG=gctrace=1 lines
Confirmed if
The heap stays near its max even right after GC, full GCs run back to back, and the GC time ratio climbs well above normal (usually past 10%). Ticks slow down across the whole server meanwhile
Ruled out if
Plenty of heap left after GC but pauses are long: GC type or settings (mem-gc)
Check with
Infra tools (no game code needed)
Sources
The Parallel CollectorOracle Parallel GC throws OutOfMemoryError if it spends more than 98% of total time in GC and recovers less than 2% of the heap
Garbage-First Garbage Collector TuningOracle By default (GCTimeRatio=12), G1 sizes the heap to keep GC time at about 8% of total time or less; full GCs caused by excessive heap occupancy show up in the log as Pause Full (G1 Compaction Pause)
A Guide to the Go Garbage CollectorGo With the default GOGC=100, the heap goal is about 2× the live heap; near the memory limit, GC runs nonstop (thrashing); GODEBUG=gctrace=1 prints GC trace output
Garbage Collector ImplementationOracle -Xlog:gc lines show the GC type (Pause Young, Pause Full), “before-GC usage->after-GC usage(heap size)”, and the pause time
dotnet-counters diagnostic tool.NET .NET 9 and later show dotnet.gc.pause.time; .NET 8 and earlier show % Time in GC since last GC