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

Buku Putih Lag Game › L10 Memori

Jeda GC stop-the-world di server Stop-the-world GC pause

ID penyebab mem-gc · Penanggung jawab utama Pengembangan server (Tim Pengembang Game) · Turut terlibat Infrastruktur server (Tim Infrastruktur)

Buka kartu interaktif dengan gambar dan simulasi →

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

Gejala
Freeze, Fast forward
Faktor
Stall
Siapa yang mengalami
Seluruh server
Kapan
Secara berkala, Makin lama menyala
Penanggung jawab
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.
Kasus nyata
Riot Games 2021: Gangguan 5 jam di League of Legends EUW: satu DB pendukung menghentikan seluruh server

Sumber

  1. Garbage-First (G1) Garbage Collector Oracle
    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
  2. JEP 523: Make G1 the Default Garbage Collector in All Environments OpenJDK
    Selama ini Serial GC dipilih sebagai default jika CPU hanya 1 atau memori kurang dari 1.792 MB; mulai JDK 27, G1 menjadi default di semua lingkungan
  3. JEP 439: Generational ZGC OpenJDK
    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
  4. JEP 189: Shenandoah: A Low-Pause-Time Garbage Collector (Experimental) OpenJDK
    Waktu jeda Shenandoah kurang lebih sama, baik untuk heap 200 MB maupun 200 GB
  5. Background garbage collection .NET
    Background GC hanya berlaku untuk pengumpulan generasi 2; pengumpulan generasi 0 dan 1 (foreground GC) menghentikan semua managed thread
  6. A Guide to the Go Garbage Collector Go
    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
  7. JEP 271: Unified GC Logging OpenJDK
    Sejak JDK 9, log GC diimplementasikan ulang dengan unified logging (-Xlog); -Xlog:gc menulis satu baris per GC seperti -XX:+PrintGC versi lama
  8. The java Command Oracle
    Tabel padanan opsi log GC lama ke -Xlog: -XX:+PrintGCDetails menjadi -Xlog:gc*
  9. 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)
  10. runtime package Go
    GODEBUG=gctrace=1: satu baris per GC, berisi wall clock time per fase, ukuran heap di awal dan akhir GC, serta target heap

Lihat juga

Lapisan yang sama: L10 Memori

Penyebab di lapisan lain dengan gejala yang sama (Freeze)

Lihat kartu interaktif dengan gambar dan simulasi