Go Runtime Mengambil Ketenangan Secangkir Teh Hijau, GreenTea GC
Mengapa Ada GC Baru Lagi?
Mengapa GC yang Ada Saat Ini?
GC Go saat ini dapat dijelaskan dengan pernyataan berikut:
- concurrent tri-color mark and sweep
- Menggunakan 3 warna (putih, abu-abu, hitam) untuk melacak status objek.
- Putih: Objek yang belum dikunjungi
- Abu-abu: Objek yang telah dikunjungi tetapi belum semua objek anak dikunjungi
- Hitam: Objek yang semua objek anaknya telah dikunjungi
- Setelah siklus selesai, semua objek berwarna putih akan dikumpulkan.
- Menggunakan Write Barrier untuk melindungi memori yang baru dibuat selama GC.
- Waktu untuk mengaktifkan/menonaktifkan Write Barrier merupakan bagian besar dari yang biasa disebut Stop-The-World (selanjutnya disebut STW).
- Melakukan proses ini secara bersamaan.
- Menggunakan 3 warna (putih, abu-abu, hitam) untuk melacak status objek.
- No Compaction
- GC Go tidak melakukan pemadatan.
- Fragmentasi memori dapat terjadi.
- Namun, objek di bawah 32kb meminimalkan fragmentasi dengan memanfaatkan cache per-P dari alokator memori (Allocator) bahasa Go.
- Non-Generational
- GC Go tidak mengelola objek berdasarkan generasi.
- Semua objek termasuk dalam generasi yang sama.
- Escape Analysis
- Go menentukan apakah objek dialokasikan di heap atau stack melalui Escape Analysis.
- Secara kasar, jika menggunakan dangling pointer atau interface, dapat dianggap dialokasikan di heap.
Yang Penting Adalah
GC Go menjelajahi semua objek dari root dan melakukan tri-color mark. Proses ini dapat diringkas dalam satu baris sebagai algoritma concurrent traversal graph topological sort
. Namun, setiap objek kemungkinan besar berada di area memori yang berbeda. Secara sederhana,
- Misalkan ada area memori yang terpisah sekitar 32MB.
- Di kedua area memori ini, masing-masing 5 objek dialokasikan.
- Objek A, B, C di area 1
- Objek D, E di area 2
- Urutan referensi objek adalah
A -> D -> B -> E -> C
. - Ketika GC dimulai, A dikunjungi, lalu D, lalu B, lalu E, lalu C.
- Pada saat ini, karena A dan D berada di area memori yang berbeda, area memori harus berpindah selama proses kunjungan A dan D.
- Dalam proses ini, biaya "memory jump" terjadi, seperti berpindah area memori dan mengisi cache line baru. Sebagian besar waktu CPU yang digunakan aplikasi dapat dialokasikan untuk tugas GC semacam ini.
- Biaya ini terus terjadi selama GC berlangsung.
Jadi, Apa Masalahnya?
Perilaku GC ini sangat merugikan dalam kasus berikut:
- Jumlah core banyak dan memori besar
- GC Go pada dasarnya dilakukan secara bersamaan.
- Namun, jika area memori luas dan objek tersebar, beberapa core akan secara bersamaan menjelajahi objek di berbagai ruang memori.
- Dalam proses ini, jika bus antara CPU dan memori tidak cukup besar, bandwidth memori dapat menjadi bottleneck.
- Selain itu, karena ada jarak fisik, setiap penjelajahan akan menjadi penundaan yang relatif besar.
- Banyak objek kecil
- Jika Anda mengoperasikan pohon atau grafik dengan kedalaman yang dalam atau banyak anak di Go, GC harus menjelajahi semua objek ini.
- Dalam proses ini, jika objek tersebar di area memori yang berbeda, penundaan akan terjadi karena alasan pertama.
- Selain itu, jika ada banyak objek kecil, GC harus menjelajahi semua objek ini, sehingga selama GC berlangsung, core CPU akan mengalokasikan banyak kapasitas untuk GC dan bekerja.
Untuk mengatasi masalah ini, tim Golang telah mengumumkan GreenTea GC.
Anda Tidak Punya Kemewahan untuk Minum Teh Hijau Lagi
Apa yang Merenggut Teh Hijau Anda?
Area yang dianggap sebagai solusi tercepat untuk GC yang ada saat ini adalah lokalitas memori. Artinya, meminimalkan memory jump dengan menempatkan objek berdekatan. Namun, pola programmer yang menulis kode tidak dapat dipaksakan, dan alokasi objek tidak dapat diprediksi tergantung pada alur kerja.
Oleh karena itu, metode yang dipilih tim Golang adalah Memory Span.
Apa itu Memory Span?
Memory span adalah tempat di mana area memori yang relatif besar dialokasikan untuk mengalokasikan objek kecil. Dan GC baru yang dinamai GreenTea GC melakukan pengumpulan sampah pada memory span ini. Operasi detailnya hampir sama dengan Tri-Color Mark and Sweep yang sudah ada.
Operasi GreenTea GC
Pertama, GreenTea GC mengalokasikan memory span. Ukurannya, seperti yang disebutkan sebelumnya, adalah 8KiB, yang memiliki ukuran tertentu. Dan di dalamnya, objek berukuran maksimum 512 bytes dapat dialokasikan. Ini adalah ukuran yang membuat Anda berpikir bahwa ukuran node pohon atau grafik yang dicontohkan, atau ukuran struct yang umumnya lolos ke heap, tidak akan lebih besar dari ini. Setiap kali objek di bawah 512 bytes lolos ke heap, objek tersebut ditumpuk di memory span ini, dan ketika memory span ini penuh, memory span baru dialokasikan.
Ketika GC terjadi, GreenTea GC menumpuk memory span ini dalam antrean dan memeriksanya secara berurutan. Dalam proses ini, GreenTea GC menggunakan penjadwalan yang hampir mirip dengan model GMP yang ada. Area seperti pencurian pekerjaan juga telah diimplementasikan. Bagaimanapun, pekerja yang mengambil memory span dari antrean memeriksa objek internal dari memory span yang dialokasikan kepadanya. Dalam proses ini, Tri-Color Mark and Sweep digunakan secara identik.
Apa Keuntungannya?
Perbedaan utama antara proses ini dan GC yang ada saat ini adalah satu: unit GC yang dilakukan sekaligus telah berubah dari objek menjadi memory span. Karena itu, GC memiliki keuntungan sebagai berikut:
- Lokalitas Memori: Karena objek terkumpul dalam memory span, memory jump diminimalkan saat menjelajahi objek. Artinya, cache CPU dapat dimanfaatkan semaksimal mungkin.
- Peningkatan Kinerja GC: Dengan melakukan GC pada unit memory span, GC bekerja lebih efisien di lingkungan multi-core.
- Optimalisasi Alokasi Memori: Karena memory span dialokasikan dengan ukuran tetap, overhead alokasi memori berkurang saat mengalokasikan objek kecil, dan kemungkinan fragmentasi berkurang. Ini meningkatkan efisiensi de-alokasi memori.
Singkatnya, mulai sekarang kita dapat mengalokasikan objek di bawah 512 bytes lebih sering dan dengan pikiran yang lebih ringan.
Namun, ada juga beberapa area yang menguntungkan di sini.
- Struktur pohon/grafik: Jika fan-out tinggi dan perubahan jarang terjadi
- B+ tree, Trie, AST (Abstract Syntax Tree)
- Struktur data yang ramah cache
- Pemrosesan batch: Alur kerja alokasi massal data kecil
- Banyak objek kecil yang dibuat oleh parsing JSON
- Objek DAO dari hasil set database
Dalam kasus-kasus ini, GreenTea GC dapat menunjukkan kinerja yang lebih baik daripada GC yang ada saat ini. Namun, ini tidak berlaku untuk semua kasus, dan khususnya ketika objek tersebar di area memori yang berbeda, peningkatan kinerja yang dramatis masih sulit diharapkan.
Jadi
Tim Golang tampaknya berniat untuk terus meningkatkan GC dalam jangka panjang. GreenTea GC ini dapat dilihat sebagai perubahan minor di area kecil, dan tidak menggantikan GC yang ada. Namun, GreenTea GC tampaknya merupakan contoh menarik yang memberikan gambaran sekilas tentang masalah yang dihadapi, atau diantisipasi, oleh tim Golang. Meskipun masalahnya kompleks, upaya untuk menyelesaikannya dengan penambahan konsep yang relatif sederhana juga sangat mengesankan. Secara pribadi, saya menganggapnya sebagai kasus yang menarik.
GreenTea GC adalah fitur eksperimental yang akan diperkenalkan mulai Go 1.25. Ini dapat diaktifkan dengan menggunakan variabel lingkungan GOEXPERIMENT=greenteagc
. Fitur ini masih eksperimental, jadi pengujian yang memadai diperlukan sebelum digunakan di lingkungan produksi.