Питання 17 · Розділ 3

Які GC мінімізують stop-the-world паузи?

4. ConcGCThreads = cores / 4 5. Уникайте великих масивів 6. SoftMaxHeapSize для повернення пам'яті

Мовні версії: English Russian Ukrainian

🟢 Junior Level

Low-latency GC — збирачі, які мінімізують паузи додатку.

Основні:

  • ZGC — паузи < 1 мс (найкращий)
  • Shenandoah — паузи < 1 мс
  • G1 — паузи 20-200 мс (компроміс)

Як вони це роблять:

  • Роблять більшу частину роботи паралельно з додатком
  • Зупиняють тільки для сканування GC Roots

🟡 Middle Level

Стратегії мінімізації

GC Стратегія Пауза
ZGC Colored Pointers + Load Barriers < 1 мс
Shenandoah Load Reference Barriers < 1 мс
G1 Регіони + Mixed GC 20-200 мс

Allocation Stall — небезпека

Додаток створює сміття швидше, ніж concurrent marking встигає завершити.
Потік додатку блокується і сам починає евакуацію об'єктів. Небезпечно: якщо stalls часті,
throughput падає ще сильніше, ніж з Parallel GC.

Порівняння

GC Типова пауза CPU overhead Throughput
Parallel 100-1000 мс Мінімальний Максимальний
G1 20-200 мс Середній Хороший
ZGC/Shenandoah < 1 мс Високий -5-15%

Generational ZGC (Java 21+)

Поділ на покоління:
  → -50% CPU overhead
  → Throughput майже як G1
  → Паузи все ще < 1 мс

Коли НЕ використовувати low-latency GC

❌ При високій CPU-утилізації бар'єри погіршать проблему — додаток витрачає більше часу на GC, ніж на роботу.
❌ Batch processing → паузи не важливі
❌ Heap < 4 ГБ → G1 ефективніший

🔴 Senior Level

Concurrent Evacuation

ZGC/Shenandoah переміщують об'єкти БЕЗ STW:
  → Додаток читає посилання → Load Barrier
  → Якщо об'єкт переїхав → Self-healing
  → G1: Evacuation = STW (обмеження)

Barrier Overhead

Write Barriers (G1):
  → При кожному запису посилання
  → ~1-2 ns overhead

Load Barriers (ZGC):
  → При кожному читанні посилання
  → ~5-15 ns overhead
  → Але Self-healing у Fast Path

Підсумок: ZGC повільніший на 5-15%

Tuning для мінімізації пауз

# ZGC
-XX:+UseZGC -XX:+ZGenerational
-XX:ConcGCThreads=4
-XX:SoftMaxHeapSize=24g

# G1
-XX:MaxGCPauseMillis=100
-XX:InitiatingHeapOccupancyPercent=45

Best Practices

  1. ZGC (Java 21+) для SLA < 10 мс
  2. G1 для SLA 100-200 мс
  3. Моніторьте Allocation Stall
  4. ConcGCThreads = cores / 4
  5. Уникайте великих масивів
  6. SoftMaxHeapSize для повернення пам’яті

Резюме для Senior

  • ZGC/Shenandoah = < 1 мс, CPU overhead 5-15% (залежить від workload та Java версії; Generational ZGC має інший overhead profile).
  • Concurrent Evacuation = ключ до low latency
  • Allocation Stall = прихована небезпека
  • Generational ZGC = найкращий баланс
  • G1 = компроміс для більшості додатків
  • Barrier overhead = ціна за низькі паузи

🎯 Шпаргалка для інтерв’ю

Обов’язково знати:

  • ZGC і Shenandoah: паузи < 1 мс через Concurrent Evacuation (об’єкти переміщуються БЕЗ STW)
  • ZGC: Colored Pointers + Load Barriers (~5-15 ns overhead при читанні); Shenandoah: Load Reference Barriers (дешевше)
  • G1: Write Barriers (~1-2 ns при запису), паузи 20-200 мс через Mixed GC + регіони
  • Allocation Stall: додаток створює сміття швидше, ніж concurrent marking; throughput падає сильніше, ніж з Parallel GC
  • Generational ZGC (Java 21+): -50% CPU overhead, throughput майже як G1, паузи все ще < 1 мс
  • Коли НЕ використовувати low-latency GC: висока CPU-утилізація (бар’єри погіршать), batch processing, Heap < 4 ГБ
  • Tuning: ZGC -XX:ConcGCThreads=4 (cores/4), G1 -XX:MaxGCPauseMillis=100

Часті уточнюючі запитання:

  • Чому ZGC/Shenandoah мають overhead 5-15%? — Barriers вставляються при кожному читанні/запису посилання; CPU витрачає час на перевірки
  • Що буде, якщо поставити MaxGCPauseMillis=10 мс для G1? — G1 не зможе вкластися → To-space exhausted → Full GC (секунди!)
  • Чому Generational ZGC кращий за single-generational? — Young GC частіші і швидші; -50% overhead; Allocation Stalls майже зникли
  • Коли G1 кращий за ZGC? — SLA 100-200 мс прийнятне, throughput важливіший; CPU-bound додатки; Heap < 4 ГБ

Червоні прапорці (НЕ говорити):

  • «ZGC не має overhead» — 5-15% throughput sacrifice за паузи < 1 мс
  • «Allocation Stall не небезпечний» — throughput падає сильніше, ніж з Parallel GC
  • «Low-latency GC завжди кращий» — для batch processing або CPU-bound завдань Parallel/G1 ефективніші

Пов’язані теми:

  • [[14. Що таке ZGC]]
  • [[15. Що таке Shenandoah GC]]
  • [[13. Що таке G1 GC]]
  • [[16. Що таке stop-the-world]]
  • [[12. Які алгоритми GC існують]]