Garbage Collection — Üçlü Takas
Önce şunu oku: Stack, Heap ve Pass-by-Value
30 saniyede özet
Çöp toplayıcı seçmek bir takas: çok iş, kısa duraklama ve az bellek aynı anda olmaz. En kısa duraklayan toplayıcı en az iş çıkaranıdır; bunu söylemeyen her karşılaştırma eksiktir.
En iyi çöp toplayıcı diye bir şey yok. Doğru soru: neyinden vazgeçmeye razısın?
Adım adım oku
- Parallel toplayıcı seyrek temizler ama temizlerken uygulamayı uzun süre dondurur.
- G1 daha sık ama daha kısa duraklar; duraklama süresi bir hedefe göre ayarlanır.
- ZGC işinin çoğunu uygulama çalışırken arka planda yapar; duraklamalar çok kısadır.
- Bunun bedeli biraz ek CPU'dur. Her toplayıcı başka bir şeyden vazgeçer.
-
Bayt: Uygulamam her şey yolundayken bir anlığına donuyor. Ne oluyor?
-
Sen: Belki çöp toplayıcı temizlik yapıyordur?
-
Bayt: Evet. Asıl soru ne zaman ve ne kadar süre temizlediği.
-
Bayt: Seyrek ama uzun, sık ama kısa ya da hiç durmadan ama biraz pahalı. Hangisi senin için?
Üçünü birden alamazsın
Üç şey birbiriyle yarışır ve hiçbir toplayıcı üçünü birden kazanmaz:
- Throughput — CPU’nun ne kadarı uygulamanın işini yapıyor
- Duraklama — en uzun stop-the-worldToplayıcının çalışabilmesi için tüm uygulama thread'lerinin durdurulduğu aralık. Gecikmeye duyarlı bir serviste p99'u bozan şey budur.Sözlükte gör → süresi
- Ayak izi — bellek ve CPU ek maliyeti
Bir toplayıcı seçmek, bu üçünden hangisinden vazgeçtiğini seçmektir.
Kafam karıştı, daha basit anlat
Çöp toplayıcı üç şeyi aynı anda en iyi yapamaz: çok iş, kısa duraklama ve az bellek. Birini iyileştirmek, genelde ötekilerden birinden ödünç almaktır.
"Stop-the-world duraklama" tam olarak neyi durdurur?
Kendin gör
GC seçimi — throughput, duraklama ve ayak izi aynı anda alınamaz
Tohum 5Young toplama
0236 ms
2458 MB genç kuşak · 4.9 sn’de bir
Full GC
05.73 sn
287 sn'de bir
En uzun duraklama
0.0 ms
Throughput
%93.3
duraklamalar %93.3 · eşzamanlı iş maliyeti düşüldü
Aynı yükte üç toplayıcı
- Parallel GC5.73 sn%93.3 throughput
- G1 GC200.0 ms%90.4 throughput
- ZGC0.5 ms%90.0 throughput
Şu an ne oldu?
Parallel GC — 0 toplama, en uzun 0 ms
Genç kuşak 4.9 sn’de bir doluyor. Duraklamanın maliyeti çöpe değil, hayatta kalan veriye bağlıdır — kopyalanan şey odur.
Aklında kalsın: Genç toplamanın maliyeti eden’in büyüklüğüyle değil, hayatta kalan nesne miktarıyla orantılıdır. Nesnelerin çoğu genç ölür, bu yüzden genç toplama ucuzdur.
Görevler0/3
Bir full GC duraklamasını göraçık
İpucu
Parallel GC ile sonuna kadar oynat. Old generation dolduğunda bütün heap’i durdurup toplar.
G1’i duraklama hedefinden vazgeçmeye zorlaaçık
İpucu
G1 seç, heap’i küçült ve ayırma hızını artır. Eşzamanlı işaretleme yetişemezse G1 full GC’ye düşer.
16+ GB heap ve 1000+ MB/sn ayırmada her duraklamayı 1 ms altında tutaçık
İpucu
Bunu yapabilen tek toplayıcı hangisi? Sonra etkili throughput’a bak: düşük duraklamanın bedeli orada.
Olay günlüğü (0)
Henüz olay yok. Oynat veya adımla.
Alttaki karşılaştırma tablosuna bak — sıralama sütuna göre değişiyor:
Parallel, 8 GB, 500 MB/sn. En uzun duraklama 5.7 saniye. Ama throughputBirim zamanda yapılan iş miktarı. GC bağlamında: CPU'nun ne kadarı uygulamanın işini yapıyor, ne kadarı toplayıcıya gidiyor.Sözlükte gör → en yüksek: %93.3.ZGC’ye geç. Duraklama 0.5 ms. Throughput ise %90 — daha düşük.- Heap’i 32 GB yap,
Parallele dön. Duraklama 5.7 sn’den 22.9 sn’ye çıktı. G1, 32 GB. Genç kuşağı 9830 MB’tan 2083 MB’a çekiyor ve 200 ms hedefini tutturuyor.G1, 2 GB, 2000 MB/sn. Hedef gitti — G1 full GC’ye düştü.- Görevleri tamamla. Sonuncusu bir seçim sorusu: büyük heap ve yoğun ayırmada her duraklamayı 1 ms altında tutan toplayıcı hangisi, bedelini nerede ödüyor?
Kafam karıştı, daha basit anlat
Hangi toplayıcının “en iyi” olduğu, neye baktığına bağlı. Duraklamaya bakarsan biri, toplam işe bakarsan öteki önde çıkar.
Heap'i 8 GB'tan 32 GB'a çıkardın ve Parallel GC kullanıyorsun. Full GC duraklamalarına ne olur?
Üç toplayıcı, üç takas
Parallel kullanan bir serviste full GC 5 saniye sürüyor. Heap'i 8 GB'tan 32 GB'a çıkarırsan duraklama ne olur? Cevabı göster
Uzar, kısalmaz. Full GC tüm eski kuşağı işaretleyip sıkıştırır, süresi eski kuşağın boyutuyla orantılıdır. Büyük heap full GC’yi yalnızca seyrekleştirir.
2 GB heap → 1.4 sn full GC 8 GB heap → 5.7 sn full GC32 GB heap → 22.9 sn full GCParallel — throughput kralı. Eşzamanlı hiçbir iş yapmaz, uygulamadan CPU çalmaz. Gece çalışan bir toplu iş için doğru tercih, kullanıcıya cevap veren bir servis için felakettir.
G1 — hedefi daha az toplayarak tutturur. -XX:MaxGCPauseMillis=200 verdiğinde genç kuşağı, hayatta kalanları kopyalamak hedefe sığacak kadar küçültür. Ayırma hızı artınca duraklama uzamaz, toplama sıklaşır.
Sınırı şu: promosyon hızı eşzamanlı işaretlemeyi geçerse G1 yetişemez ve full GC’ye düşer. Hedefi çok küçük vermek de işe yaramaz — toplama sıklığı fırlar, toplam maliyet artar.
Aşağıdaki örnek bir bankanın internet şubesinden ve kur ekranından: GC’nin toplayamadığı iki klasik sızıntı ve düzeltmesi, ardından GC’yi ayarlayıp ölçmek için bayraklar ve komutlar. Sayı yok; sayıyı kendi ölçümün verir.
Derinleş · İnternet şubesi ve kur ekranı: canlı nesneler ve ölçüm 4 dosya · ~76 satır · ilk okumada atlayabilirsin
ZGC — duraklamayı satın alır, throughput ile öder. İşaretleme ve yer değiştirme eşzamanlı olduğu için duraklama heap boyutundan bağımsızdır, 32 GB’ta da milisaniyenin altındadır.
Bedeli: her nesne okuması bir load barrier’dan geçer, düşük ayırma hızında throughput Parallel’den düşüktür. ZGC gecikmeye duyarlı servisler için doğru takastır, toplu işler için yanlış.
Her iş yükü için hangi toplayıcıyı seçersin?
Çoğu nesne genç ölür
“Nesnelerin büyük çoğunluğu genç ölür.” Tüm generational GC tasarımı bu gözleme dayanır.
Genç toplamanın maliyeti çöple değil, hayatta kalanla orantılıdır. Eden’deki 2 GB çöpün hiçbiri yaşamıyorsa toplama neredeyse bedavadır — çöp kopyalanmaz.
Pratik sonucu: çok sayıda kısa ömürlü nesne üretmek GC için ucuzdur. Pahalı olan, uzun süre hayatta kalanlardır.
Kafam karıştı, daha basit anlat
Çoğu nesne doğar, işini görür ve hemen ölür. Toplayıcı yalnızca hâlâ yaşayanları taşır, bu yüzden çok çöp ama az yaşayan varsa toplama neredeyse bedavadır.
Kuşak hipotezi (generational hypothesis) ne diyor ve neden önemli?
Tuzaklar
| Durum | Toplayıcı | Neden |
|---|---|---|
| Toplu iş, gece çalışan rapor | Parallel | Duraklama umursanmaz, throughput her şeydir |
| Tipik web servisi (< 16 GB) | G1 | Varsayılan; makul duraklama, makul throughput |
| Düşük gecikmeli servis, büyük heap | ZGC | Duraklama heap’ten bağımsız |
| Küçük konteyner, kısa ömürlü | Serial | Ek thread ve ek bellek yok |
Java 9’dan beri varsayılan G1’dir ve çoğu servis için doğru cevap odur. Toplayıcıyı değiştirmeden önce ölç:
- Ölç. GC logunu aç (
-Xlog:gc*), duraklama dağılımına bak. p99 kaç ms? - Ayırma hızını düşür. Log string’leri, ara koleksiyonlar, kutulama — azaltmak her toplayıcıda kazandırır.
- Live set’e bak. Sorun hayatta kalan veri miktarıysa bu bir önbellek ya da sızıntı sorunudur.
- Sonra toplayıcı seç.
Heap’i büyütmek ilk refleks olmamalı: genç toplamanın işini değil sıklığını azaltır, Parallel ve G1’de full GC’yi uzatır.
Kendini sına
Parallel toplayıcıda heap'i büyütmek duraklamayı kısaltır.
Parallel GC kullanan bir uygulamada full GC duraklamaları çok uzun. Heap'i 8 GB'tan 32 GB'a çıkarmak ne yapar?
Aklında kalacak üç şey
- 1 Çöp toplayıcı seçmek; çok iş, kısa duraklama ve az bellekten hangisinden vazgeçtiğini seçmektir.
- 2 Parallel toplayıcıda heap'i büyütmek uzun duraklamayı kısaltmaz, uzatır. Yalnızca daha seyrek yaşanır.
- 3 MaxGCPauseMillis bir hedeftir, garanti değil. G1 yetişemediğinde hedefi bırakır ve tam en kötü anda uzun bir duraklama yapar.
4 kart sonraki derste seni bekliyor
Bu dersin üstüne kurulanlar
Bunlar bu dersi temel alıyor; hazır olduğunda devam edebilirsin.
- Core Java & EşzamanlılıkProd'da Teşhis — Heap Dump, Thread Dump ve İlk On Beş DakikaServis yavaşladı ve ilk refleksin yeniden başlatmak. Neyi kaybediyorsun?Derse git
- Core Java & EşzamanlılıkJVM Konteynerde — Bellek Sınırı Heap'ten BüyüktürPod her gece yeniden başlıyor ama loglarda tek bir hata yok. Kim öldürüyor?Derse git