- Bahasa Go hampir tidak memiliki perilaku tak terdefinisi dan memiliki semantik GC (garbage collection) yang sederhana
- Di Go, manajemen memori manual dimungkinkan, dan ini dapat dilakukan dengan bekerja sama dengan GC
- Arena adalah struktur data untuk mengalokasikan memori secara efisien dengan masa hidup yang sama, dan artikel ini menjelaskan cara mengimplementasikannya di Go
- Menjelaskan bagaimana GC mengelola memori melalui algoritme Mark and Sweep
- Dengan menggunakan Arena, kinerja alokasi memori dapat ditingkatkan, dan hal ini dimungkinkan melalui berbagai optimisasi
- Mencoba meningkatkan performa dan meminimalkan beban GC melalui penghapusan write barrier, penggunaan ulang memori, chunk pooling, dan lain-lain
- Menyajikan pola yang aman dan cepat untuk pemrosesan memori skala besar di dunia nyata melalui fitur seperti implementasi realloc, penggunaan ulang Arena, dan inisialisasi ulang (Reset)
Ikhtisar alokasi memori manual berbasis Arena di Go
- Go adalah bahasa yang aman berkat perilaku GC yang jelas dan hampir tidak adanya Undefined Behavior
- Dengan memanfaatkan paket
unsafe, dimungkinkan melakukan kontrol memori langsung yang disesuaikan dengan implementasi internal GC
- Artikel ini menjelaskan cara membuat allocator memori berbasis struktur Arena di Go yang dapat bekerja sama dengan GC
Definisi dan kebutuhan Arena
- Arena adalah struktur untuk mengalokasikan objek dengan masa hidup yang sama secara efisien
- Jika
append biasa memperluas array secara eksponensial, Arena menambahkan blok baru dan menyediakan pointer
- Antarmuka standarnya adalah sebagai berikut:
Alloc(size, align uintptr) unsafe.Pointer
Cara kerja pointer dan GC
- GC bekerja dengan cara menandai (mark) dan mengambil kembali (sweep) memori
- Untuk GC yang presisi, digunakan metadata bernama pointer bits yang memberi tahu posisi pointer
- Jika pointer ditangani secara keliru di dalam Arena, GC dapat gagal melacak pointer sehingga berpotensi menimbulkan error use-after-free
Metode perancangan Arena
- Struktur Arena memiliki field berikut:
- Semua alokasi diproses dengan alignment 8 byte, dan jika tidak cukup maka dibuat chunk baru dengan
nextPow2
- Chunk dialokasikan sebagai tipe
struct { A [N]uintptr; P *Arena }, bukan []uintptr, sehingga GC dapat melacak Arena
Cara menjamin keamanan pointer di Arena
- Jika menggunakan pointer yang dialokasikan hanya di dalam Arena, GC akan mempertahankan seluruh Arena
- Dengan mengatur pointer agar mereferensikan Arena, kelangsungan hidup seluruh Arena dijamin oleh GC
- Metode alokasi Arena melakukan hal berikut:
- Menyimpan pointer Arena di akhir chunk dalam
allocChunk()
Hasil benchmark performa
- Dibandingkan
new bawaan, alokasi Arena menunjukkan peningkatan performa rata-rata 2~4 kali atau lebih
- Bahkan dalam situasi dengan beban GC tinggi, pendekatan Arena menunjukkan performa lebih baik hingga lebih dari 2 kali
- Optimisasi seperti penghapusan write barrier dan pemanfaatan
uintptr memberikan peningkatan performa hingga 20% pada alokasi kecil
Strategi penggunaan ulang chunk dan penghilangan heap
- Penggunaan ulang chunk dimungkinkan dengan memanfaatkan
sync.Pool
- Melalui
runtime.SetFinalizer(), chunk dapat dikembalikan ke pool saat Arena menghilang
- Performanya sangat membaik pada alokasi kecil, tetapi pada alokasi besar bisa lebih lambat daripada
new
Fitur inisialisasi ulang dan penggunaan ulang Arena
- Dengan metode
Reset(), Arena dapat dikembalikan ke keadaan awal
- Meskipun risikonya besar, struktur yang sama dapat digunakan kembali tanpa realokasi memori
- Saat digunakan kembali, chunk juga dipakai ulang sehingga performa meningkat drastis
Implementasi fitur Realloc
- Dengan mengimplementasikan fungsi
realloc di Arena, ekspansi dinamis dimungkinkan untuk alokasi terbaru
- Jika tidak memungkinkan, memori baru dialokasikan lalu isinya disalin
Kesimpulan dan penyediaan kode lengkap
- Dengan memahami secara mendalam mekanisme GC di Go dan berdasarkan implementasi internalnya, penulis menyelesaikan manajer memori berbasis Arena
- Strukturnya memiliki keamanan dan performa sekaligus, dan jika digunakan dengan tepat sangat berguna untuk menangani struktur data berskala besar
- Kode implementasi lengkap mencakup struct Arena serta
New, Alloc, Reset, allocChunk, finalize, dan lainnya
1 komentar
Komentar Hacker News
Artikel ini menarik untuk dibaca
Reference[T]yang menyediakan fungsi yang samaBaru-baru ini saat melakukan performance tuning di Go, saya akhirnya menggunakan desain arena yang sangat mirip untuk memaksimalkan performa
unsafeBeberapa perbaikan yang mudah
caplebih agresif sebelum memanggil append bawaanunsafe.Stringberguna untuk meneruskan string dari byte slice tanpa alokasiIni di luar topik, tetapi saya suka minimap di sampingnya
Ringkasan untuk orang yang enggan membaca artikel panjang
unsafeuntuk mempercepat kerja allocatorunsafe.Pointer, GC tidak bisa melihat dengan benar apa yang dirujuk di arena dan dapat membebaskannya secara tidak sengajareflect.StructOfuntuk membuat tipe baru yang menyertakan field pointer tambahan ke blok-blok iniTerkait: diskusi tentang penambahan "wilayah memori" ke standard library
Ini menarik
Go memprioritaskan agar ekosistem tidak rusak
Catatan meta singkat