Garbage collection (GC) Go'da, dilin erken sürümlerinde ortaya çıkan otomatik bir bellek yönetimi mekanizmasıdır. Tarihsel olarak, Go'daki GC performansa etkisi nedeniyle eleştirilen bir konu olmuştur. Ancak, dilin gelişimi ile birlikte, özellikle Go 1.5 sürümünden sonra önemli ölçüde iyileştirilmiştir: şu anda minimum duraklama süresi ile çalışan üçlü eşzamanlı (concurrent, tricolor, mark-and-sweep) bir çöp toplayıcı kullanılmaktadır.
Sorun büyük sayıda geçici nesne oluşturan programlarda veya kullanılmayan yapılar üzerindeki referansları silmeme durumlarında ortaya çıkar: bu GC üzerindeki yükü artırır ve büyük duraklamalara yol açabilir. Nesne türlerine, döngüsel referanslara ve yığın dışında kalan uzun referans zincirlerine dikkat edilmesi önemlidir.
Çözüm bellek tahsisini izlemek, GOGC çevre değişkeni aracılığıyla GC'yi profil çıkarmak ve ayarlamak, iç döngülerde ve kritik alanlarda tahsisat sayısını en aza indirmektir. Go'daki çöp toplamanın sadece yığın (heap) için çalıştığını, yığında tahsis edilen her şeyin görünürlük alanından çıkarken otomatik olarak silindiğini ve "yığına giden" nesnelerin GC tarafından kontrol edildiğini unutmamak önemlidir.
Örnek kod:
// Tahsisatı profil çıkarma ve GC optimizasyonu import ( "runtime" "fmt" ) func main() { var memStats runtime.MemStats runtime.ReadMemStats(&memStats) fmt.Printf("Tahsisattan önce: %d bytes ", memStats.Alloc) s := make([]int, 1_000_000) for i := range s { s[i] = i } runtime.GC() // manuel temizleme runtime.ReadMemStats(&memStats) fmt.Printf("GC sonrasında: %d bytes ", memStats.Alloc) }
Anahtar özellikler:
GOGC çevre değişkeni ile ayarlanabilir (örneğin, GOGC=100 — standarttır; düşürmek, GC'yi hızlandırır ancak CPU tüketimini artırır).Hangi nesnenin "yığına gittiğini" ve hangisinin "yığın" üzerinde kaldığını nasıl anlayabiliriz?
Cevap: Bunun için, go build -gcflags="-m" derleyici bayrağı ile analiz edilebilen escape analysis kullanılır. Fonksiyondan dışarı dönen veya closure'larda kullanılan nesneler genellikle yığına gider.
Örnek kod:
func escape() *int { v := 42 return &v // v yığında olacak }
GC, yığındaki nesneler dahil, tüm değişkenler üzerinde etkili midir?
Hayır, GC yalnızca yığın (heap allocated objects) ile çalışır. Yığın üzerinde tahsis edilen her şey, fonksiyon tamamlandığında otomatik olarak temizlenir.
Manuel çağrı runtime.GC() önemli ölçüde performansı artırabilir mi?
Aksine, manuel çağrı genellikle CPU tüketimini artırarak performansı düşürür. Yalnızca testler veya hata ayıklama durumları için kullanılmalıdır.
runtime.GC() çağrısıOlumsuz durum
Bir geliştirici, her istekte yeni büyük dilim (slice) oluşturarak hizmet yazıyor, bunların yaşam döngüsü hakkında düşünmüyor. Bu, GC üzerindeki yükün hızla artmasına, ani duraklamalara ve performans düşüşüne yol açar.
Artıları:
Eksileri:
Olumlu durum
Bir geliştirici, hizmeti optimize eder, tahsisatları profil çıkarır, sync.Pool aracılığıyla tamponları yeniden kullanır, GC çağrı sayısını azaltır ve sıcak noktalarda bellek tahsisini en aza indirir.
Artıları:
Eksileri: