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

Анатомия игровых лагов › L10 Память

Трешинг GC (мало свободного места в куче) GC thrashing (heap nearly full)

ID причины mem-gc-thrash · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Открыть карточку в основной версии с иллюстрациями и экспериментами →

Когда живые данные приближаются к пределу кучи, GC почти нечего освобождать, и сборки идут одна за другой без перерыва.

Почему Из-за роста онлайна на событии или утечки живые данные заполняют кучу почти до предела → Следствие GC освобождает совсем немного, и сразу снова запускается Full GC, большую часть CPU занимает GC → На экране Весь сервер несколько минут то уходит в слоумо, то ловит фризы, а затем падает из-за нехватки памяти

Симптомы
Слоумо, Фриз, Дисконнект
Факторы
Остановка
У кого
Весь сервер
Когда
Вечерний пик, При наплыве игроков, Чем дольше без перезапуска
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Задавать размер кучи с запасом относительно живых данных в пик (обычно как минимум в 2 раза больше), сокращать долгоживущие данные и утечки.
Команда инфраструктуры: задачи
Настроить алерт на долю времени GC, перезапускать сервер сразу, не дожидаясь, что он справится сам, брать инстансы с запасом памяти, чтобы можно было увеличить кучу.
Цифры для ориентира
Если GC занимает больше 10% времени работы, это обычно считают тревожным сигналом. Некоторые сборщики в Java выдают ошибку нехватки памяти, если тратят на GC 98% времени и почти ничего не освобождают.
На графике
Упор в лимит (плато) · куча сразу после GC, доля времени GC
Где смотреть
Смотреть, насколько куча после GC близка к максимальной и какую долю времени занимает GC. Для Java смотреть «после GC(размер кучи)» в строках -Xlog:gc и частоту строк Pause Full, для .NET dotnet-counters (в .NET 8 и ниже % Time in GC since last GC, с .NET 9 прирост dotnet.gc.pause.time), для Go интервалы между строками GODEBUG=gctrace=1
Подтверждает
Даже сразу после GC куча остаётся почти полной, Full GC идут один за другим, доля времени GC сильно выше обычной (как правило, больше 10%). Всё это время тик замедляется на всём сервере
Опровергает
Если после GC в куче есть запас, а паузы всё равно длинные, дело в выборе и настройке сборщика (mem-gc)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)

Источники

  1. The Parallel Collector Oracle
    Parallel GC выдаёт OutOfMemoryError, если тратит на GC больше 98% всего времени и освобождает меньше 2% кучи
  2. Garbage-First Garbage Collector Tuning Oracle
    По умолчанию (GCTimeRatio=12) G1 подбирает размер кучи так, чтобы GC занимал не больше примерно 8% времени. Full GC из-за слишком заполненной кучи ищут в логе по строкам Pause Full (G1 Compaction Pause)
  3. A Guide to the Go Garbage Collector Go
    При GOGC=100 по умолчанию целевой размер кучи примерно в 2 раза больше живой кучи. Если упереться в лимит памяти, GC работает без остановки (трешинг). GODEBUG=gctrace=1 выводит трассировку GC
  4. Garbage Collector Implementation Oracle
    Строка -Xlog:gc содержит тип GC (Pause Young, Pause Full), «занято до GC->занято после GC(размер кучи)» и длительность паузы
  5. dotnet-counters diagnostic tool .NET
    В .NET 9 и новее это dotnet.gc.pause.time, в .NET 8 и ниже % Time in GC since last GC

Смотрите также

Тот же слой: L10 Память

Причины с тем же симптомом (Слоумо) на других слоях

Карточка в основной версии с иллюстрациями и экспериментами