Bu makale, çöp toplama algoritmalarına genel bir bakış ve Java ve Python gibi bazı popüler programlama dillerinde çöp toplamanın nasıl uygulandığı dahil olmak üzere çöp toplamayı tanıtmaktadır. Buna girmeden önce, çöp toplamanın artılarını ve eksilerini ele alalım. Bellek ayırma hataları için neden bu kadar yaygın bir çözümdür? Çöp toplamayı kullanmayan C ve C++ gibi dillerde bellek yönetiminin tehlikeleriyle başlayacağız.
C/C++’da bellek yönetiminin tehlikeleri
Bellek ayırma sorunları, potansiyel hatalara ve güvenlik açıklarına neden olan C/C++’da yaygın olan sorunların yalnızca bir alt kümesidir, ancak bunlar büyük bir alt kümedir ve izini sürüp düzeltmesi çok can sıkıcıdır. Bellek ayırma hataları aşağıdaki senaryoları içerir:
- Ayırdığınız belleğin serbest bırakılmaması, bu da sonunda sistemdeki tüm RAM’i kullanabilir ve yalnızca programı değil, tüm bilgisayarı çökertebilir.
- Bellek potansiyel olarak rastgele sonuçlarla serbest bırakıldıktan sonra bir işaretçi aracılığıyla arabellek okumaya veya yazmaya çalışmak (diğer adıyla sarkan işaretçi).
- Bellek yöneticisini ve sonunda programı ve hatta tüm sistemi çökertebilen bir bellek bloğunu iki kez serbest bırakmak.
Diğer yaygın C/C++ güvenlik açıkları, arabellek taşmalarını ve kodun üzerine veri yazabilen dize manipülasyonunu içerir. “Eğlenceli” kısım, bir saldırganın verileri kötü niyetli yürütülebilir kod olacak şekilde hazırlaması ve ardından kodu çalıştırmayı başarmasıdır.
Bekleyin bekleyindiyorsun: korumalı mod sistemindeki ayrı kod ve veri segmentleri nedeniyle bu artık gerçekleşemez. Ne yazık ki, bazı durumlarda hala olabilir ve oluyor. Bir dizgede bir SQL deyimi oluşturan ve ardından yürütme için bir veritabanına gönderen ve genellikle bir SQL enjeksiyon güvenlik açığı oluşturan bir program buna bir örnektir. Elbette, SQL enjeksiyon güvenlik açıklarından kaçınmak için iyi belgelenmiş en iyi uygulamalar var, ancak bu kategorideki yeni hatalar veritabanı istemcilerinde artmaya devam ediyor, bu nedenle her programcının en iyi uygulamaları takip etmediği açık.
Çöp toplama: Kusurlu tedavi
Çöp toplamayı kullanmak, ana bellek tahsisi ve serbest bırakma sorunlarını tamamen ortadan kaldırabilir, ancak bunun bir bedeli vardır. En büyük sorunlar, çöp toplayıcının ek yüküdür; çöp toplayıcı çalışmaya karar verdiğinde öngörülemeyen duraklamalar; ve bir sunucu işlemi durduğunda artan gecikme. İkinci sorun genellikle Java tabanlı sunucu programlarında ortaya çıkar.
Çöp toplamanın ek yükü önemli olabilir ve bellek ile performans arasında bir değiş tokuşu içerir. 2005’e göre kağıt Matthew Hertz ve Emery D. Berger tarafından:
[W]Beş kat daha fazla belleğe sahip, kopyalanmayan olgun bir alana sahip Appel tarzı bir kuşak toplayıcı, erişilebilirlik tabanlı açık bellek yönetiminin performansıyla eşleşir. Toplayıcı, yalnızca üç kat daha fazla bellekle, açık bellek yönetiminden ortalama %17 daha yavaş çalışır. Ancak, yalnızca iki kat daha fazla bellekle, çöp toplama performansı yaklaşık %70 oranında düşürür. Fiziksel bellek az olduğunda, disk belleği çöp toplamanın açık bellek yönetiminden çok daha yavaş çalışmasına neden olur.
Appel tarzı kuşak toplayıcılar muhafazakar çöp toplayıcılardır; daha agresif GC’ler bazen daha az bellekle daha iyi performans gösterebilir.
Durmalar ve gecikme, GC tabanlı dillerin, gecikmeyi en aza indirmesi gereken gerçek zamanlı programlar ve yüksek verimli sunucular için yetersiz olabileceği anlamına gelir. Örneğin, gerçek zamanlı Lisp ve gerçek zamanlı Java’da, tümü çöp toplayıcıyı değiştiren veya ortadan kaldıran birkaç girişim oldu.
Son zamanlarda, birkaç Java ve Scala sunucusu GC olmayan dillerde yeniden yazıldı; örneğin, C++’da Cassandra’nın yeniden yazılmış hali olan Scylla ve öncelikle C++’da yazılmış bir Kafka eklentisinin yerine geçen Redpanda. Hem Scylla hem de Redpanda’da gecikme, orijinal sunuculara kıyasla büyük ölçüde azaldı. Her ikisi de aynı yük için çok daha küçük kümeler gerektirir.
Çöp toplama algoritmaları
Çöp toplama için düzinelerce algoritma var. En önemli algoritmalardan bazılarına ve göze çarpan özelliklerine bakalım.
Referans sayımı
Referans sayımında program, tahsis edilen kaynağın bir parçası olarak bir kaynağa yapılan referansların, işaretçilerin veya tutamaçların sayısını depolar ve referanslar eklendikçe veya kaldırıldıkça sayımı artırır veya azaltır. Referans sayısı sıfıra ulaştığında, kaynak serbest bırakılabilir. Bellek çöp toplama, referans sayma uygulamalarından yalnızca biridir; ayrıca sistem nesnelerinin, Windows COM nesnelerinin ve dosya sistemi bloklarının veya dosyalarının serbest bırakma kontrolü için kullanılır.
Referans saymanın iki önemli dezavantajı vardır: aşırı sık güncellemeler ve döngüsel referanslar. Güncellemelerin sıklığını kontrol etmenin bir yolu, derleyicinin ilgili nesneleri gruplandırmasına izin vermektir. Sayıların sıfıra ulaşmasını engelleyen döngüsel referansları ele almanın bir yolu, ulaşılamayan döngüleri kaldırmak için ara sıra bir izleme GC’si çalıştırmaktır.
Çöp toplama izleme
İzleme GC, referans sayımına en önemli alternatiftir ve aşağıdaki tüm algoritmaların yanı sıra birkaç tane daha içerir. Çöp toplamayı izlemenin genel fikri, izleme sürecinin bazı kök nesnelerle (geçerli yerel değişkenler, genel değişkenler ve geçerli işlev parametreleri gibi) başlaması ve hangi nesnelerin erişilebilir olduğunu belirlemek için referansları takip etmesidir. Ulaşılamayan tüm nesneler daha sonra çöp toplanır. Çöp toplamanın izlenmesi o kadar yaygındır ki bazen basitçe çöp toplama olarak adlandırılır.
İşaretle ve süpür
1960 yılında yayınlanan ve geçmişi 1960 yılına kadar uzanan “saf” işaretleme ve tarama algoritması John McCarthy ve Lisp, önce sistemi dondurarak, ardından kök kümeden erişilebilen tüm nesneleri “in-use” olarak işaretleyerek çalışır. Üçüncü adım, tüm belleği taramak ve “in-use” olarak işaretlenmemiş herhangi bir bloğu serbest bırakmaktır. Son olarak, bir sonraki koleksiyona hazırlanmak için kalan tüm bellek bloklarında “in-use” biti temizlenir ve sisteme izin verilir Açıkçası bu, gerçek zamanlı sistemler için uygun değil.
İşaretle ve süpür’deki bir değişken, belleğin üç “renğini” kullanır: beyaz bloklara erişilemez ve algoritma sona erdiğinde hala beyaz kümedeyseler serbest bırakılmaya mahkumdurlar; siyah bloklara köklerden erişilebilir ve beyaz kümedeki nesnelere giden referansları yoktur; ve gri bloklara köklerden erişilebilir, ancak “beyaz” nesnelere referanslar için henüz taranmaları gerekir. Algoritma tamamlandıktan sonra, gri blokların tümü siyah kümede toplanır. Tipik olarak, ilk işaretleme, kökler tarafından başvurulan tüm blokları gri kümeye ve diğer tüm blokları beyaz kümeye koyar.
Üç renkli varyant algoritmasının üç adımı vardır:
- Gri kümeden bir nesne seçin ve onu siyah kümeye taşıyın.
- Referans verdiği her beyaz nesneyi gri kümeye taşıyın. Bu, ne bu nesnenin ne de referans verdiği herhangi bir nesnenin çöp olarak toplanamayacağını garanti eder.
- Gri grup boşalana kadar son iki adımı tekrarlayın.
Gri küme boş olduğunda, tüm beyaz bloklar serbest bırakılabilir. Üç renkli algoritma, program çalışırken arka planda gerçekleştirilebilir; hala ek yük var ama “dünyayı durdurmuyor”.
Koleksiyonu kopyalama
Koleksiyon kopyalamanın genel fikri, diğer adıyla yarı-uzay GC, belleği “uzaydan-uzay” ve “to-uzaya” olarak adlandırılan iki eşit boyutlu bölgeye ayırmanızdır. bölgelerin rollerini değiştirir ve canlı nesneleri uzaydan uzaya kopyalar, uzaya uzayın sonunda bir boş alan bloğu bırakır (tüm erişilemeyen nesneler tarafından kullanılan belleğe karşılık gelir).
Koleksiyonun kopyalanmasıyla ilgili zorluklar vardır. En büyüğü blokları kopyaladığınızda adreslerinin değişmesi; bunun bir çözümü, bir yönlendirme adresleri tablosu tutmaktır. Diğer bir büyük sorun da, koleksiyonu kopyalamak için işaretleme ve süpürme için yaptığınızdan iki kat daha fazla belleğe ihtiyaç duymanızdır. Koleksiyonun kopyalanması, belleğin çoğu çöpse işaretle ve süpür’den daha hızlıdır, ancak çoğu belleğe erişilebilirse daha yavaştır.
İşaretle ve sıkıştır
Mark ve kompakt koleksiyon, esasen tek bir bellek alanı içinde çalışan koleksiyonu kopyalamaktır. Mark-compact toplayıcı, erişilebilir tüm nesneleri tarar ve bunları yığının altında sıkıştırır, bu da yığının üstünü tüketim için kullanılabilir bırakır. Mark ve kompakt koleksiyonun en büyük dezavantajı, aldığı zamandır.
kuşak koleksiyonu
Kuşak koleksiyonu, yığını nesnelerin yaşına, yani kuşaklara göre birden fazla alana (genellikle iki veya üç) böler. Genel olarak, yeni nesnelerin çöp olma olasılığı eski nesnelerden daha fazladır, bu nedenle yeni nesneleri çöp için taramak ve çoğu zaman eski nesneleri olduğu gibi bırakmak mantıklıdır. Bazı kuşak toplayıcılar, farklı kuşaklarda farklı tarama frekansları ve/veya toplama algoritmaları kullanır.
Çöp toplama hangi dillerde kullanılır?
Lisp, John McCarthy’nin 1958’de icat ettiğinden beri çöp toplamayı kullandı. Java, Scala, Python ve .NET/C#’nin tümü popüler GC dilleridir. Ek çöp toplama dilleri, nispeten yeni Go, Ruby, D, OCaml ve Swift’in yanı sıra daha eski diller Eiffel, Haskell, ML, Modula-3, Perl, Prolog, Scheme ve Smalltalk’ı içerir.
Java, Python ve .NET/C#, çöp toplamayı uygulayan daha popüler programlama dillerinden bazılarıdır. Java sanal makinesi (JVM) aslında dört farklı çöp toplayıcı sağlar: seri, paralel, eşzamanlı işaretleme ve tarama ve G1GC, çöp ilk çöp toplayıcı. G1GC artık Java’da varsayılandır; yumuşak gerçek zamanlı hedeflere ulaşan, bölgeselleştirilmiş ve kuşaksal bir paralel sıkıştırma toplayıcıdır.
Python, özellikle standart CPython uygulaması, referans sayımını üç seviyeli kuşak koleksiyonuyla birleştirir bu yalnızca konteyner nesnelerini temizlemeye odaklanır. .NET CLR (ortak dil çalıştırma zamanı), bir üç seviyeli nesil işareti ve kompakt toplama algoritması. CLR ayrıca bellek nesnelerini biri büyük nesneler (85.000 bayt veya daha yüksek) ve diğeri küçük nesneler için olmak üzere iki kümeye ayırır; büyük nesne yığını genellikle sıkıştırılmaz, sadece işaretlenir ve süpürülür, ancak gerekirse sıkıştırılabilir.
Çözüm
Gördüğünüz gibi, çöp toplamayı halletmenin epeyce yolu var ve bunların çoğunun kendi kullanımları var. Daha olgun çöp toplama uygulamaları, birden çok algoritmayı birleştirir ve gecikmeyi en aza indirmek için yıllar içinde yoğun bir şekilde ayarlanmıştır.
Telif hakkı © 2023 IDG Communications, Inc.
Kaynak : https://www.infoworld.com/article/3685493/what-is-garbage-collection-automated-memory-management-for-your-programs.html#tk.rss_all