Garbage Collector nasıl çalışır?
Bu flood’da .net CLR - Common Language Runtime
'daki Garbage Collector
üzerinden çöp toplayıcıların nasıl çalıştığını kısaca anlatacağım.
C/C++/Pascal gibi dillerle yazılan uygulamalar direkt olarak makine koduna dönüştürülerek çalıştırılır. .NET, Java, Python gibi dillerde yazılan uygulamalar ise bir runtime
tarafından çalıştırılırlar. runtime
'a sahip olmanın en önemli avantajlarından biri uygulamanın hafıza yönetimini runtime
'ın otomatik olarak yapmasıdır. runtime
uygulamanın hafıza isteklerini işletim sisteminden önceden aldığı hafıza alanından karşılar, uygulamanın hafıza alanı ile işi bittiğinde ise geri alır. Hafızanın geri alınması görevini Garbage Collector - GC
yapar.
GC
otomatik hafıza yönetimi ile uygulama yazımını kolaylaştırmakta, kodlama süresini kısaltmaktadır. Yine GC
, makine koduna derlenen dillere göre kodlama hatalarından dolayı karşılaşılan hafıza alanlarının leak
edilmesi problemi ile de bir seviyeye kadar baş edebilmektedir.
Şimdi GC
'nin CLR
'da nasıl uygulandığını inceleyelim. CLR
uygulamalara sağladığı hafızayı 3 jenerasyona ayırır. Jenerasyon 0, 1 ve 2. Yeni oluşturulan nesneler ilk olarak jenerasyon 0'a atılır. GC
koşarak uygulamada artık referansı kalmayan objeleri temizler. Jenerasyon 0'da bulunan objelerden kullanılmaya devam edenler jenerasyon 1'e taşınır, jenerasyon 1'de bulunan ve kullanılmaya devam eden objeler ise jenerasyon 2'ye taşınır. Bir objenin jenerasyon 2'de olması demek objenin uygulama tarafından uzun süre referans edilmesi demektir.
Jenerasyon arası geçişler aşağıdaki şekilde gösterilmiştir. GC
koştuğunda uygulamada referansı kalmayan ve temizlenen objeler bulanıklaştırılmış diğer objeler ise bir sonraki jenerasyona geçirilmişlerdir.
Hafızanın üç jenerasyona bölünmesinin sebebi GC
performansını artırmaktır. Yapılan jenerasyon sınıflandırması ile GC
'nin her seferinde bütün objelerin referanslarını kontrol etmesi gerekmez ve çöp toplama süreci daha hızlı bir şekilde tamamlanabilir.
GC
çalıştığında uygulamada artık referans edilmeyen objeleri temizler, hafıza fragmantasyonunu engellemek için de temizlikle boşalan alanları hala kullanılmakta olan objeleri taşımak suretiyle birleştirir. Hafıza fragmantasyonunun önemi aşağıdaki şekilde gösterilmiştir.
Hafıza alanlarının fragmantasyonu GC
ile önlenir ve uygulamanın büyük objeleri tutmak için ihtiyaç duyacağı hafıza alanları yaratılmış olur. Fragmante durumda ise hafızada yeterli toplam alan olsa bile büyük objeleri koymak üzere uygun hafıza alanı bulunamayabilir.
GC
hafıza alanlarının yerlerini değiştirme gibi tehlikeli işlemler yaptığı için GC
yapılan Thread
koşarken uygulamadaki diğer bütün Thread
'lerin geçici olarak durdurulması gerekmektedir. Buna GC Pause
denir ve sistem GC
sürecinde işlevini gerçekleştiremez.
Birçok uygulama GC
'nin sebep olduğu bu küçük (10-200 ms) duraklamaları fonksiyon kaybı olmadan ve kullanıcı fark etmeden tolere edebilecek durumdadır. Real Time
(gerçek zamanlı) sistemler bu kapsamda değildir. Bu sebeple Real Time
sistemler GC
olan dillerde yazılamazlar.
GC
koşarken uygulamadaki bütün Thread
'lerin durdurulur fakat Thread
'ler GC
için herhangi bir anda durdurulamaz. Thread
'ler ancak ve ancak GC
çalışmasına uygun Safe Point
'lerde durdurulabilirler. Safe Point
'ler Thread
'lerin herhangi bir mutex
almadığı, catch
, finally
gibi bloklarda olmadığı yerlerdir. CLR
uygulamayı çalıştırırken kodun uygun yerlerine Safe Point
sıçrama noktaları enjekte eder. GC
başlayacağı zaman öncelikle Thread
'lere durdurma isteği gönderilir, bütün Thread
'ler Safe Point
'lere gelene kadar beklenir.
Anlaşılacağı üzere bazı özel durumlarda ilgili Thread
'in hata işlemesi veya mutex
tutması çok uzun sürüyorsa bütün Thread
'lerin Safe Point
'e ulaşması daha uzun süreceği için GC Pause
olması gerekenden daha uzun sürer ve yüklü bir sistem performans kaybı yaşar.
Son olarak, performansın çok kritik olduğu sistemlerde CLR
'dan GC
'nin devreye girmek üzere olduğu ile ilgili bildirim alınarak sistemin yükü hafifletilerek kullanıcıların duraklamadan etkilenmemesi sağlanabilir. Bu senaryo biraz ekstrem gelebilir ancak milisaniyelerin bile önemli olduğu finansal (özellikle borsa, döviz, vb) işlemlerde bu tarz detaylara bile dikkat edilmelidir.
İlerleyen flood’larda GC
performansını artırmak için kullanılabilecek yöntemlere göz atacağız.