Çöp toplayıcıları yığın taşmasını nasıl önler?


23

Böylece çöp toplayıcıların nasıl çalıştığını düşünüyordum ve ilginç bir konu düşündüm. Muhtemelen çöp toplayıcıları tüm yapıların aynı şekilde geçiş yapması gerekir. Bağlantılı bir listeden ya da dengeli bir ağaçtan ya da her neyse geçtikleri havayı bildiklerini bilmiyorlar. Ayrıca, aramalarında çok fazla bellek kullanamazlar. Olası bir yol ve TÜM yapıları geçmeyi düşündüğüm tek yol, hepsini tekrarlı bir şekilde ikili bir ağaç gibi izlemeniz olabilir. Bununla birlikte, bu bağlantılı bir listede yığın taşması veya hatta zayıf dengelenmiş bir ikili ağaç verir. Ama şimdiye kadar kullandığım dilleri toplayan çöplerin, bu tür durumlarla başa çıkmakta hiçbir problemleri yok gibi görünüyor.

Ejderha kitabında, "Sıralanmamış" sıraları kullanır. Temel olarak yapıya tekrarlı bir şekilde geçmek yerine, sadece bir sıra olarak işaretlenmesi gereken şeyleri ekler ve sonunda işaretlenmeyen her şey için silinir. Fakat bu sıra çok geniş olmaz mıydı?

Öyleyse, çöp toplayıcıları keyfi yapıları nasıl geçiyor? Bu geçiş tekniği taşmayı nasıl önler?


1
GC, tüm yapıları aşağı yukarı aynı şekilde kaydırır, ancak yalnızca çok soyut bir anlamda (bkz. Cevap). Bir şeyi somut olarak takip etmeleri, ders kitaplarında bulabileceğiniz temel sunumlarda belirtilenden çok daha karmaşık. Ve özyinelemeyi kullanmazlar. Ayrıca, sanal bellek ile, kötü uygulamalar nadiren bellek taşması olarak GC yavaşladığını gösterir.
babou

İzleme için gereken alan hakkında endişeleniyorsunuz. Ancak, izlenen ve kullanımda olduğu bilinen ve potansiyel olarak yeniden doldurulabilir bellekten ayırt etmek için gereken alan veya yapılardan ne haber? Bu, büyük olasılıkla yığın boyutuyla orantılı olarak önemli bir bellek maliyetine sahip olabilir.
babou

16 ya da bayttan daha büyük bir nesne boyutunda bir bitvektörle yapılacağını düşündüm, böylece baş üstü en az 1000 kat daha az olacaktı.
Jake,

Bunu yapmanın pek çok yolu vardır (cevaba bakınız) ve bunlar izlemede de kullanılabilir, bu daha sonra sorunuzu cevaplayacaktır (bitvektörler veya bitmapler önerdiğiniz yığın veya kuyruk yerine izleme için kullanılabilir). Çok sayıda nesnenin olabileceği küçük nesneler üzerinde yer israf etme niyetinde olmadığınız sürece, tüm nesnelerin büyük olduğunu varsayamazsınız ve o zaman alan için endişelenmenize gerek yoktur. Sanal bellekte iseniz, alan çoğu zaman daha az sorun yaratır ve sorunlar çok farklıdır.
babou

Yanıtlar:


13

Çöp toplama uzmanı olmadığımı unutmayın. Bu cevap sadece tekniklere örnekler verir. Çöp toplama tekniklerine temsili bir genel bakış olduğunu iddia etmiyorum.

Taranmamış bir sıra ortak bir seçimdir. Sıra, potansiyel olarak en derin veri yapısı kadar büyük olabilir. Kuyruk, genellikle çöp toplama ipliğinin yığında değil, açıkça depolanır.

Bir düğümün çocuklarından biri hariç tümü tarandıktan sonra, düğüm taranmamış sıradan kaldırılabilir. Bu temelde bir kuyruk çağrısı optimizasyonu. Çöp toplayıcıları en son düğümün en derin çocuğunu taramaya çalışmak için buluşsal bulgular içerebilir; Örneğin Lisp'te için GC taraması gereken cara consönce cdr.

Taranmamış bir sıra tutmaktan kaçınmanın bir yolu, işaretçileri yerinde değiştirmek ve çocuğun geçici olarak ebeveyne işaret etmesini sağlamaktır. Bu, çöp toplayıcıları dışındaki bağlamlarda kullanılan, sabit bellekli bir ağaç geçiş tekniğidir. Bu tekniğin dezavantajı, GC bir veri yapısını geçerken, veri yapısının geçersiz olması, dolayısıyla GC'nin dünyayı durdurması gerektiğidir. Bu bir anlaşma kırıcı değil: birçok çöp toplayıcı, sonucu olarak çöpü kaçıramayan ancak özleyemeyen aşamalara ek olarak, dünyayı durduran bir aşamayı da içeriyor.


2
Son paragrafta açıklanan teknik genellikle " işaretçi ters " olarak adlandırılır .
Wandering Logic

@WanderingLogic Evet, işaretçi ters çevirme işlemi kendi cevabımla nasıl adlandırdığımdır. Deutsch, Schorr ve Waite (1967) 'den kaynaklanmaktadır. Bununla birlikte, bunu sabit bir bellekte çalışır duruma yanlıştır: bu gerektirir ile, her bir hücre için ekstra bit s Bu bit yığınları kullanarak azaltılabilir da, işaretçiler. Başvurduğunuz kabul edilen cevap aynı sebeple ya da tam olarak doğru değil. log2pp
babou

I olan bu ekstra bit gerek kalmadan özel bir GC işaretçi tersine kullanılır; İşin püf noktası, hafızadaki nesnelerin özel bir hafıza içi temsilini kullanmaktı. Yani, "başlık" nesnesi ortada, başlıktan önce işaretçi alanlarıyla ve sonradan işaretçi olmayan alanlarla; dahası, tüm işaretçiler hizalandı ve başlık, her zaman ayarlanan en az anlamlı biti olan bir alanı içeriyordu. Böylelikle, işaretçi geri dönüş işlemi sırasında, bir sonraki göstericiye ulaşmak ve bir nesneyle bitirdiğimizi fark etmek, ekstra bitler olmadan açık bir şekilde yapılabilir. Bu düzen aynı zamanda OOP kalıtımını destekledi.
Thomas Pornin,

@ThomasPornin Biraz bilginin bir yerde olması gerektiğini düşünüyorum. Soru nerede? Bunu sohbette tartışabilir miyiz? Şimdi gitmem gerekiyor ama bunun altına inmek istiyorum. Veya web üzerinden ulaşılabilir bir tanım var mı?
babou

1
@babou ve Thomas lütfen
Gilles '

11

Özetle : Çöp toplayıcıları özyineleme kullanmaz. Sadece iki kümeyi (birleştirebilecek) izleyerek izlemeyi kontrol ederler. İzleme ve hücre işleme sırası, kümeleri temsil etmek için hatırı sayılır bir uygulama özgürlüğü sağlayan alakasızdır. Bu nedenle, bellek kullanımında aslında çok ucuz olan birçok çözüm vardır. Yığın hafızası bittiğinde GC tam olarak çağrıldığından bu önemlidir. Yeni sayfalar kolaylıkla ayrılabilir olarak şeyler, büyük sanal anılarla biraz farklıdır ve ennemy alanı eksikliği, ancak veri eksikliği değildir mevkiinde .

Varsayın, çöp toplayıcıları izlemeyi düşünüyorsunuz , sorunuzun uygulanmadığı durumlarda referans sayımı yapmıyorsunuz.

Soru, bir kümeyi takip etmek için izlemenin bellek maliyetine odaklanıyor : hala izlenemeyen işaretçiler içeren erişilebilir bellek hücrelerinin grubu (izlenmemiş olanlar için). Bu çöp toplama için sadece hafıza sorunun yarısı . GC, başka bir kümeyi de takip etmelidir: işlemin sonunda diğer hücrelerin geri kazanılması için erişilebilir olduğu bulunan tüm hücrelerin V (ziyaret için) seti . Birini tartışıp diğerini tartışmamak, aynı maliyete sahip olabileceği, benzer çözümler kullanabileceği ve hatta bir araya getirilebileceği için sınırlı bir anlam ifade eder.UV

Unutulmaması gereken ilk şey, tüm izleme GC'nin, bellek hücrelerinin köşeler ve işaretçilerin yönlendirilmiş kenarlar olduğu programdan erişilebilen bellekteki yönlendirilmiş hücre grafiğinin sistematik olarak araştırılmasına dayanan aynı soyut modeli izlemesidir. Bunun için aşağıdaki setleri kullanır:

  • zaten mutator tarafından erişilebilir durumda bulunan hücrelerin seti (ziyaret edilmiş) , yani GC'nin gerçekleştirildiği program veya algoritma. V grubu iki ayrık alt gruba ayrılır: V = U T ;VVV=UT

  • henüz izlenmemiş işaretçilere sahip ziyaret edilen hücrelerin grubu (takip edilmemiş);U

  • tüm işaretçilerinin izlendiği ziyaret edilen hücrelerin seti (izlenen).T

  • Ayrıca , kullanımda olsun veya olmasın, kümedeki tüm hücrelerin kümesini not edin .'H

Algoritmanın çalışması için sadece ve U veya U ve T'nin bir şekilde gösterilmesi gerekir.VUUT

Algoritma, çalışma zamanı sistemi tarafından bilinen bazı kök işaretçilerden başlar (genellikle yığın ayrılmış bellekteki işaretçiler) ve izlemeyen kümesine işaret ettikleri tüm hücreleri koyar (dolayısıyla V de).UV

UcVUcUT

UUV=TV'H-VV

VUUT

Ayrıca hücre nedir, bir boyutta mı, çok sayıda mı geldiğine, bunlarda işaretçileri nasıl bulduğumuza, bunların nasıl sıkıştırılabileceğine ve çöp toplama ile ilgili kitap ve anketlerde bulabileceğiniz diğer teknik sorunlara ilişkin bir çok ayrıntıya atlarım. .

U

Bilinen uygulamaların farklı olduğu yerlerde, bu kümelerin gerçekte temsil edilme şekilleri farklıdır. Aslında birçok teknik kullanılmıştır:

  • bit eşlemi: Hücrenin adresi kullanılarak bulunabilen her bir hafıza hücresi için bir biti bulunan bir harita için bir miktar hafıza alanı korunur. İlgili hücre, harita tarafından tanımlanan kümedeyken bit açıktır. Eğer sadece bit haritalar kullanılıyorsa, hücre başına sadece 2 bit gerekir.

  • alternatif olarak, her hücrede özel bir etiket biti (veya 2) işaretlemek için yeriniz olabilir.

  • günlük2pp

  • hücrenin içeriği ve işaretçilerine ilişkin bir yüklemeyi test edebilirsiniz.

  • Hücreyi, yalnızca temsil edilen kümeye ait olan hücrelerin tümü için tasarlanan boş bir belleğe yerleştirebilirsiniz.

  • VTTU

  • Aslında bu teknikleri tek bir set için bile birleştirebilirsiniz.

Daha önce de belirtildiği gibi, yukarıdakilerin tümü, bazıları göründüğü kadar garip olan bazı çöp toplayıcılar tarafından kullanılmıştır. Hepsi uygulamanın çeşitli kısıtlamalarına dayanır. Ve sonuç olarak önemli olmadıklarından, bellek kullanımında oldukça ucuz olabilirler, muhtemelen bu amaç için serbestçe seçilebilecek sipariş politikalarının işlenmesiyle yardımcı olabilirler.

En garip görünen, hücreleri yeni bir alana transfer eden, gerçekte çok yaygındır: buna kopya koleksiyonu denir. Daha çok sanal bellek ile kullanılır.

Açıkça, özyinelemenin olmadığı ve mutator algoritma yığınının kullanılması gerekmediği belirtildi.

Bir başka önemli nokta, birçok modern GC'nin büyük sanal anılar için uygulanmış olmasıdır . Daha sonra uygulama yapmak ve fazladan liste veya yığın oluşturmak için yeni sayfalar kolayca tahsis edilebildiğinden sorun olmaz. Bununla birlikte, büyük sanal hatıralarda, düşman alan yetersizliği değil, alan yetersizliğidir . Daha sonra, kümeleri temsil eden yapı ve bunların kullanımı, veri yapısının ve GC uygulamasının yerinin korunmasına yönelik olmalıdır . Sorun uzay değil zamandır. Yetersiz uygulamaların bellek taşma durumundan ziyade kabul edilemez yavaşlama gösterme olasılığı daha yüksektir.

Bu tekniklerin çeşitli kombinasyonlarından kaynaklanan birçok spesifik algoritmaya referans vermedim, bu yeterince uzun görünüyor.


4

Yığın taşmasını önlemenin standart yolu açık bir yığın kullanmaktır (yığında bir veri yapısı olarak depolanır). Bu da bu amaçlar için çalışıyor. Çöp toplayıcılar genellikle bu role hizmet eden, incelenmesi / gezilmesi gereken maddelerden oluşan bir çalışma listesine sahiptir. Örneğin, "Taranmamış" sıranız tam olarak bu tür bir kalıp örneğidir. Sıra potansiyel olarak büyük olabilir, ancak yığın taşmasında depolanmadığından yığın taşmasına neden olmaz. Her durumda, yığıntaki canlı nesnelerin sayısından asla daha büyük olmayacaktır.


GC çağrıldığında, yığın genellikle doludur. Başka bir nokta, yığının ve yığının aynı bellek alanının her iki ucundan büyümesidir ..
babou

4

Çöp toplamanın "klasik" tanımlarında (örneğin, Mark Wilson, " Tek İşlemcili Çöp Toplama Teknikleri ", Bellek Yönetimi Konusunda Uluslararası Atölye Çalışması , 1992, ( alternatif bağlantı ) veya Andrew Appel'in Modern Derleyici Uygulamasında (Cambridge University Press, 1998)), koleksiyonerler “Mark and Sweep” veya “Copying” olarak sınıflandırılır.

Mark ve Sweep koleksiyonerleri @ Gilles'in cevabında açıklandığı gibi pointer-ters kullanarak ekstra alana ihtiyaç duymaz. Appel, Knuth'un gösterge tersine çevirme algoritmasını Peter Deutsch ve Herbert Schorr ve WM Waite'e atfettiğini söyledi.

Çöp toplayıcıları kopyalamak, fazladan alana ihtiyaç duymadan sıra geçişi gerçekleştirmek için genellikle Cheyney'in algoritması olarak adlandırılanı kullanır . Bu algoritma, CJ Cheyney, "Algoritmayı Sıkıştıran Bir Rekürrem Olmayan Liste", Comm. ACM , 13 (11): 677-678, 1970.

Bir kopyalama çöp toplayıcısı olarak size denilen toplamaya çalıştıklarını bellek yığını var dan-uzay ve aradığınız kopyaları için kullandığınız belleğin bir yığın için uzayı . Boşluk, scanen eski kopyalanan ancak taranamayan kaydı freegösteren bir işaretçi ve boşluktaki bir sonraki boş konuma işaret eden bir işaretçi ile bir sıra olarak düzenlenir . Wilson’un gazetesinden bu resmi:

Cheyney algoritması örneği

Her öğeyi uzayda tararken, çocuklarını uzaydan uzayda işaretleyiciye kopyalar freeve ardından işaretçiyi uzayda uzaydan çocuğun yeni kopyasına boşluğa değiştirirsiniz. Veri yapılarınız ağaç olmadığında (bir çocuğun birden fazla ebeveyni olabilir) kullanmanız gereken ilave bir numara vardır. Bu durumda, bir çocuğu uzaydan uzaya kopyaladığınızda, çocuğun eski sürümünün üzerine , yeni bir yönlendirme işaretçisiyle üzerine yazmanız gerekir . O zaman, çocuğun eski sürümüne başka bir gösterici taradığınızda, bunun zaten kopyalandığını farkedersiniz ve bir daha kopyalamayın.


Aslında, cevabımda açıklandığı gibi, hem Mark + Sweep hem de Copy koleksiyonu aynı soyut grafik algoritmasıdır. MS ve Copy koleksiyonu, yalnızca soyut algoritmanın kullandığı kümeler bakımından farklılık gösterir ve her iki aile de, birçok değişkenle birlikte, cevabımda açıklanan küme uygulama tekniklerinin bir kombinasyonuna dahil edilir. Bazı GC varyantları aslında aynı GC'de MS ve Kopyayı karıştırır. MS ile Kopya'yı birbirinden ayırmak, bazıları tarafından kitapları yapılandırmak için uygun bir yol olarak görülüyor, ancak bu keyfi bir seçim ve eski moda vizyonun olduğuna inanıyorum.
babou

@babou: Eğer biri ziyaret edilen her şeyin kopyalanacağı bir kopyalama algoritması kullanıyorsa (yavaş, ancak çalışma setinin hiç bu kadar büyük olmadığı küçük platformlarda faydalı olabilir), bazı algoritmalar kullanabildiğinden beri basitleştirilmiş olabilir. Hafıza eskiden bir yere yerleştirilmiş bir nesne tarafından bir karalama defteri olarak işgal edildi. Biri aynı zamanda, her okunmadan önce ve sonra nesnenin geçerliliğini kontrol etmesi ve bir nesnenin taşınması durumunda iletme işaretçisini izlemesi koşuluyla, toplama sırasında nesnelere salt okunur erişimler gerçekleştirmesi için sınırlı bir yetenek kazanabilir.
supercat

@supercat Ne söylemeye çalıştığınızdan, amacınızın ne olduğundan emin değilim. İfadelerinizden bazıları doğru görünüyor. Ancak GC döngüsü sona ermeden önce uzaydan nasıl kullanabileceğinizi anlamıyorum (iletici işaretçiler içerir). Ve ne için bir karalama defteri olurdu? Algoritmayı basitleştirin nasıl? GC yapılırken uygulanan çoklu mutator ipliklerle ilgili olarak, bu ciddi bir şekilde uygulanmasını etkileyebilmesine rağmen, büyük ölçüde dikey bir konudur. Yorumlarda bunu ele almaya çalışmam. Salt okunur erişimde daha az sorun yaratması gerekir, ancak şeytan ayrıntıda gizlidir.
babou
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.