2011-10-02 28 views
16

我見過垃圾收集器被標記爲很多東西 - 代代等。但是我看到Boehm GC標記爲「保守」。這到底是什麼意思呢?保守的垃圾收集器

回答

23

垃圾收集器必須掃描所有對象和調用(執行堆棧)以識別正在執行的程序中的所有「活動」地址,然後「收集」沒有「活動」地址的對象。在某些環境中,GC算法可能是精確的,並且確切知道什麼是對象地址,什麼不對。在其他環境中,它必須掃描部分存儲(最着名的是執行堆棧),其中有可能是對象地址的存儲字,並且假設CONSERVATIVE假設它看起來像一個有效地址,並且存在一個對象地址,那麼不應該收集對象。

保守收集有一些優點,最值得注意的是,代碼生成器(如果沒有解釋的話)可以隨時隨地分配變量,並且不需要嚴格追蹤哪些是對象指針。 (跟蹤對象指針位置的需求可能會導致優化程度較低的代碼,此外還會使代碼生成器變得相當複雜。另外,保守的收集器有一些合理的機會,可用於從未打算支持的編譯器垃圾收集,而精確的收集器會要求編譯器徹底改變)。

保守方法的主要缺點是不能實現完整的「複製」收集器。複製完成後,必須更新指向複製對象的指針,並且如果不清楚給定位值是否爲對象指針或僅是數值,則無法安全地確定該對象是否應該被修改複製。還有一個缺點是,由於隨機位模式看起來像他們的地址,一些「死」的對象最終可能不會被收集,儘管在實踐中這不是一個嚴重的問題。

+1

如果對象引用存儲爲句柄而不是直接指針,則可以實現複製收集器。在沒有硬件支持的情況下,基於句柄的方法往往比使用直接指針的方法慢,但在具有硬件支持的多處理器系統中,基於句柄的方法可能具有優勢。當然,如果人們試圖判斷什麼可能或可能不是對象引用,它們當然會有巨大的優勢。 – supercat

+0

@supercat什麼樣的系統對此有硬件支持? – Pepijn

+0

@Pepijn:我不知道任何現有的硬件都不會支持這樣的事情,而不會強加16,384個對象限制(按照今天的標準,這當然會很可笑)。但是,如果有人正在設計一個旨在優化面向對象框架中的性能的下一代架構,那麼適量的硬件就有可能爲垃圾收集提供大量的幫助。例如,分代或併發垃圾收集的一個重要要求是知道哪些對象已被修改,因爲... – supercat

5

一個保守的垃圾收集器是一個不知道給定的單詞是否是一個指針。如果單詞指向已分配的堆塊,那麼垃圾收集器會保守地假定這個單詞是一個指針,因此不會回收該堆塊或任何被認爲可以從中訪問的內容。

這種方法的主要優點是它可以收集不可達的值,而不必與編譯器協調工作。但是,它有很多缺點:

  1. 看起來像指針的值通過防止部分堆被回收而導致內存泄漏。這對於32位地址空間來說是一個更大的問題,因爲如果分配了GB的RAM,幾乎每個int都將指向一個堆塊。

  2. 確定單詞是否指向已分配的堆塊需要搜索堆緩慢且(客觀)不必要的堆。

  3. GC無法移動堆塊,因爲它不能更新指針,因爲它不知道它們在哪裏。

  4. 隱藏指針或在堆塊外使用指針的代碼會使保守的GC崩潰。數字食譜代碼和Boehm GC出現了這個問題,儘管因爲NR C代碼違反了C規範。

這些缺點嚴重到足以使生產垃圾收集器儘可能不保守。

+1

你的觀點2是相當錯誤的。在設計正確的設置中,確定指針是否處理有效分配是非常有效的。 –

+0

@HotLicks:實現通常搜索間隔樹,通常會在標記階段的內部循環中引發幾個超速緩存內存讀取。與不必在準確的收集器中進行搜索相比,這是緩慢的。 –

+0

我工作的實現更有效率。對於小對象,陣列中的大小相似,因此可以計算對象邊界,並且可以針對每個陣列的位向量來檢查對象有效性。 –