GC-тюнінг – це не магія сеньйорів, а набір повторюваних патернів.
Ти перестаєш гадати, чому сервіс підвисає щоранку о 9:03, і починаєш керувати паузами як дорослий інженер.
Правильні патерни тюнінгу GC дають три бонуси:
стабільні latency без раптових фризів,
менші рахунки за залізо,
аргументи, щоб не дати менеджеру спихнути все на «ну ти ж щось там не так накрутив у JVM».
Інструменти
| № | Патерн / інструмент | Ключовий показник (metric) | Типова ціль / орієнтир | Коли порівнювати |
|---|---|---|---|---|
| 1 | Мінімізація пауз | GC pause P95, ms | < 50–100 ms для онлайн сервісів | При аналізі latency API, UI, платежів |
| 2 | Максимізація пропускної здатності | Оброблені запити/події за годину | Максимум при прийнятних паузах | Для batch job, ETL, масових розрахунків |
| 3 | Контроль розміру heap | Heap usage %, Xms/Xmx | 60–85% при стабільному навантаженні | При плануванні RAM, виборі лімітів у контейнерах |
| 4 | Робота з young generation | Minor GC / сек, young gen usage % | Часті, але короткі minor GC без promotion failure | Веб/мікросервіси з великою кількістю короткоживучих обʼєктів |
| 5 | Робота з old generation | Old gen occupancy %, GC pause P99 | Old gen < 70–80%, паузи стабільні | Сервіси з кешами, сесіями, довгоживучими даними |
| 6 | Оптимізація Eden space | Eden refill time, MB/s alloc | Eden не заповнюється миттєво, але й не простоює | Піки навантаження, спайки трафіку |
| 7 | Тюнінг Survivor space | Survivor usage %, promotion rate % | Немає mass-promotion в old, survivor не переповнений | При рості old gen після піків навантаження |
| 8 | Зменшення promotion failure | Кількість promotion failure / год | ≈ 0 подій за годину | Після збільшення навантаження або зміни схеми кешування |
| 9 | Уникнення частих Full GC | Full GC / добу | < 1–2 Full GC / добу | При скаргах на раптові фризи системи |
| 10 | Обмеження алокацій у пікових потоках | Allocation rate, MB/s | Зниження alloc rate без втрати бізнес-логіки | Аналіз гарячих endpoint-ів та потоків обробки |
| 11 | Pre-allocation структур | Pre-allocation hit ratio, % | > 80% звернень до вже виділених структур | Парсери, цикли, обробка логів |
| 12 | Оптимізація object pooling | Pool reuse ratio, % | > 70–80% reuse без contention | Гарячі обʼєкти з частим створенням/знищенням |
| 13 | Зменшення тимчасових обʼєктів | Обʼєктів/операцію, alloc MB/s | Вдвічі менше обʼєктів/операцію у гарячих шляхах | Після профайлінгу коду (JFR, async-profiler) |
| 14 | Tuning G1GC pause targets | MaxGCPauseMillis, ms | Target 50–200 ms під SLO | G1GC на проді, коли паузи стрибають |
| 15 | Tuning G1GC regions | Розмір регіону, MB | 1–4 MB для більшості сервісів | При аналізі ефективності mixed/young GC в G1 |
| 16 | Tuning G1GC mixed cycles | Mixed GC / хвилину, reclaimed MB | Стабільний reclaim без піків пауз | Коли old gen повільно, але впевнено зростає |
| 17 | Tuning G1 InitiatingHeapOccupancyPercent | IHOP %, heap at cycle start % | Старт циклу при 30–45% heap | Коли GC запускається або занадто рано, або запізно |
| 18 | Tuning G1 ReservePercent | Reserve %, old gen occupancy % | 5–15% резерву без OOM | При тупиках через забитий old gen |
| 19 | Tuning ParallelGC threads | GC threads count | GC threads ≈ CPU cores або трохи менше | Для batch, heavy CPU job з ParallelGC |
| 20 | Tuning ZGC heap fragmentation | Fragmentation %, relocation thrash | Низька фрагментація при паузах < 10 ms | Low-latency сервіси з ZGC |
| 21 | Tuning ZGC relocation set | Relocated MB / цикл | Релокація не створює піків CPU | Високе навантаження на heap з ZGC |
| 22 | Tuning ZGC concurrent cycles | ZGC cycles / хвилину | Стабільна частота циклів без starvation | Прод-трафік з нерівномірними піками |
| 23 | Tuning Shenandoah evacuation | Evacuated MB / цикл | Ефективний репак без росту пауз | JVM на Shenandoah у Linux/RedHat |
| 24 | Tuning Shenandoah pacing | Pacing overhead %, pause time | Низький pacing overhead при стабільному latency | Коли Shenandoah дає непередбачувані спайки |
| 25 | Tuning metaspace limits | Metaspace MB, GC for metadata / год | Метадані без неконтрольованого росту, немає OOM | Динамічне завантаження класів, плагіни |
| 26 | Tuning compressed oops | Heap size GB, oops enabled | Використання compressed oops до ~32 GB | Великі сервіси з heap 8–32 GB |
| 27 | Tuning compressed class pointers | Class space MB | Compressed class pointers увімкнені | Велика кількість модулів / класів |
| 28 | Зменшення частоти safepoint | Safepoint time %, events / хв | Safepoint < 5% CPU часу | При підозрі, що стопи не від GC |
| 29 | Уникнення частих stop-the-world | STW pause P95, ms | Рідкі та короткі STW-паузи | Коли юзери бачать реальні фризи |
| 30 | Розподіл heap по поколіннях | Young/old ratio %, survivor size % | Баланс без promotion storm і OOM | Після змін моделі памʼяті або трафіку |
| 31 | Правильний розподіл thread stack | Thread stack size KB, threads count | Немає stack overflow й зайвого overcommit | Багатопотокові сервіси, thread pools |
| 32 | Tuning DirectByteBuffer usage | Direct memory MB, buffer count | Direct memory < ліміту, без OOM Direct buffer | Netty/NIO сервіси |
| 33 | GC-friendly data structures | Garbage/op, allocations/op | Менше обʼєктів на бізнес-операцію | Перехід на primitive/легкі колекції |
| 34 | Уникнення розмитих посилань | Ref-cleared events, cache hit ratio | Кеш не здувається при першому GC | Кеші на Soft/Weak reference |
| 35 | Tuning reference processing | Reference queue lag, ms | Малий lag обробки reference-черг | Інтенсивне використання Soft/Weak/Phantom |
| 36 | Tuning string deduplication | Dedup ratio %, string heap MB | Високий dedup ratio та економія heap | JSON/XML heavy сервіси, логування |
| 37 | Tuning interned strings | Intern table size, lookups/sec | Таблиця intern без вибухового росту | DSL, SQL/JPQL, власні мови |
| 38 | Tuning off-heap кешів | Off-heap cache MB, hit ratio % | Значна економія heap при стабільному hit ratio | Великі кеші, каталоги, карти |
| 39 | Tuning netty buffer sizes | Avg buffer size, fragmentation % | Мінімум дрібних алокацій, низька фрагментація | Netty/gRPC/кастомні протоколи |
| 40 | Tuning thread-local caches | ThreadLocal hit ratio %, memory per thread | Високий hit ratio без зайвого споживання памʼяті | Гарячі серіалізатори, форматери, парсери |
| 41 | Tuning allocation rate | Allocation rate MB/s, GC cycles / хв | Зниження alloc rate → менше GC циклів | Після ідентифікації гарячих алокацій |
| 42 | Tuning object lifetime distribution | Short-lived vs long-lived %, objects | Чітко розділені профілі життєвого циклу | Мікс кешів, потоків подій, сесій |
| 43 | Tuning finalizers avoidance | Finalizable objects count | ~0 обʼєктів з фіналізаторами | Легасі-код, старі бібліотеки |
| 44 | Tuning cleaner tasks | Cleaner queue lag, cleaned objects/sec | Стабільний cleanup без піків пауз | Канали, сокети, файли |
| 45 | Tuning GC logging verbosity | GC log volume MB/добу | Логи дають картину, але не забивають диск | Прод-сервіси з аналізом логів |
| 46 | Аналіз GC логів | К-сть проаналізованих релізів/квартал | Кожен великий реліз має GC-ревʼю | Регулярні релізи, зміни трафіку |
| 47 | Інтеграція GC метрик у Prometheus | GC metrics coverage %, кількість дашбордів | Є дашка з GC-паузами, heap, Full GC | Усі важливі прод-сервіси |
| 48 | Контроль GC пауз у SLA | % запитів у SLO | > 99% запитів укладаються у latency SLO | Платіжні, критичні сервіси з контрактами |