Selama server Java atau C# menghentikan semua thread untuk mengumpulkan garbage (stop-the-world), seluruh server berhenti.
Mengapa Heap penuh, GC dimulai → Akibatnya Semua thread game dihentikan untuk pengumpulan garbage (makin banyak data hidup, makin lama) → Di layar Semua pemain di server berhenti bersamaan, lalu fast forward
Penanggung jawab utama Pengembangan server (Tim Pengembang Game) · Turut terlibat Infrastruktur server (Tim Infrastruktur)
Tugas Tim Pengembang Game
Tetapkan GC dengan jeda singkat (ZGC, Shenandoah, G1 dengan target jeda lebih kecil) secara eksplisit lewat opsi startup, kurangi alokasi, sesuaikan ukuran heap.
Tugas Tim Infrastruktur
Pilih instance dengan memori yang cukup untuk heap yang longgar, alokasikan minimal 2 CPU dan memori minimal sekitar 1,8 GB untuk container (JDK 26 dan versi sebelumnya memilih Serial GC sebagai default jika kurang dari itu), pantau waktu jeda GC.
Kisaran angka
Minor GC, yang hanya mengumpulkan objek baru (young generation), butuh beberapa hingga puluhan ms. Full GC yang mengumpulkan seluruh heap dengan data hidup beberapa GB bisa memakan lebih dari 1 detik. Jeda ZGC kurang dari 1 ms dan hampir tidak bergantung pada ukuran heap. Jeda Shenandoah juga singkat karena tidak sebanding dengan ukuran heap.
Di grafik
Melonjak secara berkala · Waktu tick server, waktu jeda GC
Yang diperiksa
Aktifkan log GC, lalu tumpangkan waktu dan lama jeda di grafik waktu tick server. Java: baris Pause dari opsi startup -Xlog:gc* (JDK 8 ke bawah: -XX:+PrintGCDetails); .NET: metrik jeda GC di dotnet-counters (.NET 9 ke atas: dotnet.gc.pause.time, 8 ke bawah: % Time in GC since last GC); Go: baris yang ditulis GODEBUG=gctrace=1 setiap kali GC berjalan
Cocok jika
Lonjakan tick dan jeda GC terjadi di waktu yang sama, lama jeda kira-kira sama dengan lama lonjakan. Semua zona dan channel di server melonjak bersamaan
Tidak cocok jika
Tidak ada jeda panjang di log GC, tetapi tick tetap melonjak: lebih mungkin penyebab lain seperti lock, pemanggilan sinkron, atau penulisan disk. Hanya satu zona yang melonjak: lebih mungkin GC engine skrip (mem-script-gc) atau beban di zona itu
Sarana pemeriksaan
Tools infrastruktur (tanpa perlu kode game)
Pelajari lebih lanjut
Target jeda G1 di Java secara default 200 ms per jeda, setara dengan 4 tick di server 20 tick. Jika container diberi kurang dari 2 CPU atau memori kurang dari sekitar 1,8 GB, Java versi JDK 26 dan sebelumnya memilih Serial GC sebagai GC default. Serial GC mengumpulkan garbage dengan satu thread, sehingga jedanya jauh lebih panjang. Server C# (.NET) biasanya mengaktifkan server GC dan background GC, tetapi pengumpulan generasi 0 dan 1 (Gen0/1) yang menampung objek baru, serta Full GC yang disertai kompaksi, tetap menghentikan semua thread. Jeda GC di Go biasanya kurang dari 1 ms, tetapi jika alokasinya banyak, pihak yang meminta memori harus ikut mengerjakan sebagian tugas GC sehingga tick melambat. Apa pun mekanismenya, jika alokasi lebih cepat daripada pengumpulan, thread game akhirnya tetap berhenti. G1 beralih ke Full GC, sedangkan ZGC menghentikan thread yang meminta memori sampai pengumpulan selesai.
Garbage-First (G1) Garbage CollectorOracle Target jeda G1 default 200 ms (MaxGCPauseMillis); jika memori habis saat pengumpulan, G1 beralih ke Full GC yang menghentikan semua thread dan melakukan kompaksi pada seluruh heap
JEP 439: Generational ZGCOpenJDK Jeda ZGC maksimal 1 ms dan tidak bergantung pada ukuran heap, jeda G1 beberapa ms hingga beberapa detik. Jika alokasi lebih cepat daripada pengambilan kembali memori, ada risiko allocation stall
Background garbage collection.NET Background GC hanya berlaku untuk pengumpulan generasi 2; pengumpulan generasi 0 dan 1 (foreground GC) menghentikan semua managed thread
A Guide to the Go Garbage CollectorGo GC Go sebagian besar berjalan secara konkuren dan hanya punya jeda stop-the-world yang singkat; jika alokasinya banyak, goroutine ikut mengerjakan tugas GC (assist) sehingga timbul keterlambatan
JEP 271: Unified GC LoggingOpenJDK Sejak JDK 9, log GC diimplementasikan ulang dengan unified logging (-Xlog); -Xlog:gc menulis satu baris per GC seperti -XX:+PrintGC versi lama
The java CommandOracle Tabel padanan opsi log GC lama ke -Xlog: -XX:+PrintGCDetails menjadi -Xlog:gc*
dotnet-counters diagnostic tool.NET .NET 9 ke atas menampilkan meter System.Runtime (dotnet.gc.pause.time dan lainnya), .NET 8 ke bawah menampilkan EventCounter lama (% Time in GC since last GC dan lainnya)
runtime packageGo GODEBUG=gctrace=1: satu baris per GC, berisi wall clock time per fase, ukuran heap di awal dan akhir GC, serta target heap