GC 模組

GC 模組提供介面給 Ruby 的標記和清除垃圾收集機制。

部分底層方法也可以透過 ObjectSpace 模組取得。

你可以透過 GC::Profiler 取得 GC 執行資訊。

常數

INTERNAL_CONSTANTS

垃圾收集器的內部常數。

OPTS

GC 建置選項

公開類別方法

add_stress_to_class(class[, ...]) 按一下切換原始碼

在配置給定類別的執行個體時引發 NoMemoryError

static VALUE
rb_gcdebug_add_stress_to_class(int argc, VALUE *argv, VALUE self)
{
    rb_objspace_t *objspace = &rb_objspace;

    if (!stress_to_class) {
        set_stress_to_class(rb_ary_hidden_new(argc));
    }
    rb_ary_cat(stress_to_class, argv, argc);
    return self;
}
auto_compact → true 或 false 按一下切換原始碼

傳回是否已啟用自動壓縮。

static VALUE
gc_get_auto_compact(VALUE _)
{
    return RBOOL(ruby_enable_autocompact);
}
auto_compact = flag 按一下切換原始碼

更新自動壓縮模式。

啟用時,壓縮器會在每個主要收集時執行。

啟用壓縮會降低主要收集的效能。

static VALUE
gc_set_auto_compact(VALUE _, VALUE v)
{
    GC_ASSERT(GC_COMPACTION_SUPPORTED);

    ruby_enable_autocompact = RTEST(v);

#if RGENGC_CHECK_MODE
    ruby_autocompact_compare_func = NULL;

    if (SYMBOL_P(v)) {
        ID id = RB_SYM2ID(v);
        if (id == rb_intern("empty")) {
            ruby_autocompact_compare_func = compare_free_slots;
        }
    }
#endif

    return v;
}
compact 按一下切換原始碼

此函式會將 Ruby 堆疊中的物件壓縮在一起。它會將物件移至未使用的空間中,藉此消除堆疊中的未使用空間(或碎片)。此函式會傳回一個雜湊,其中包含有關已移動物件的統計資料。有關壓縮統計資料的詳細資訊,請參閱 GC.latest_gc_info

此方法為實作特定,預計除了 MRI 之外,不會在任何實作中實作。

要測試是否支援 GC 壓縮,請使用慣用語法

GC.respond_to?(:compact)
static VALUE
gc_compact(VALUE self)
{
    /* Run GC with compaction enabled */
    gc_start_internal(NULL, self, Qtrue, Qtrue, Qtrue, Qtrue);

    return gc_compact_stats(self);
}
count → Integer 按一下以切換來源

GC 執行次數。

它會傳回自程序啟動以來 GC 執行的次數。

# File gc.rb, line 105
def self.count
  Primitive.gc_count
end
disable → true 或 false 按一下以切換來源

停用垃圾回收,如果垃圾回收已停用,則傳回 true

GC.disable   #=> false
GC.disable   #=> true
# File gc.rb, line 69
def self.disable
  Primitive.gc_disable
end
enable → true 或 false 按一下以切換來源

啟用垃圾回收,如果垃圾回收先前已停用,則傳回 true

GC.disable   #=> false
GC.enable    #=> true
GC.enable    #=> false
# File gc.rb, line 57
def self.enable
  Primitive.gc_enable
end
latest_compact_info → hash 按一下以切換來源

傳回最近一次 GC 壓縮中移動的物件資訊。

傳回的 hash 有兩個金鑰::considered 和 :moved。:considered 的 hash 會列出壓縮器考慮移動的物件數目,而 :moved 的 hash 會列出實際上已移動的物件數目。有些物件無法移動(可能是因為已固定),因此可以使用這些數字來計算壓縮效率。

static VALUE
gc_compact_stats(VALUE self)
{
    size_t i;
    rb_objspace_t *objspace = &rb_objspace;
    VALUE h = rb_hash_new();
    VALUE considered = rb_hash_new();
    VALUE moved = rb_hash_new();
    VALUE moved_up = rb_hash_new();
    VALUE moved_down = rb_hash_new();

    for (i=0; i<T_MASK; i++) {
        if (objspace->rcompactor.considered_count_table[i]) {
            rb_hash_aset(considered, type_sym(i), SIZET2NUM(objspace->rcompactor.considered_count_table[i]));
        }

        if (objspace->rcompactor.moved_count_table[i]) {
            rb_hash_aset(moved, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_count_table[i]));
        }

        if (objspace->rcompactor.moved_up_count_table[i]) {
            rb_hash_aset(moved_up, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_up_count_table[i]));
        }

        if (objspace->rcompactor.moved_down_count_table[i]) {
            rb_hash_aset(moved_down, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_down_count_table[i]));
        }
    }

    rb_hash_aset(h, ID2SYM(rb_intern("considered")), considered);
    rb_hash_aset(h, ID2SYM(rb_intern("moved")), moved);
    rb_hash_aset(h, ID2SYM(rb_intern("moved_up")), moved_up);
    rb_hash_aset(h, ID2SYM(rb_intern("moved_down")), moved_down);

    return h;
}
latest_gc_info → hash 按一下以切換來源
latest_gc_info(hash) → hash
latest_gc_info(:major_by) → :malloc

傳回最近一次垃圾回收的資訊。

如果給定選用引數 hash,則會覆寫並傳回它。這是為了避免探測效應。

# File gc.rb, line 266
def self.latest_gc_info hash_or_key = nil
  Primitive.gc_latest_gc_info hash_or_key
end
malloc_allocated_size → Integer 按一下以切換來源

傳回由 malloc() 分配的記憶體大小。

僅在使用 CALC_EXACT_MALLOC_SIZE 建置 ruby 時才可用。

static VALUE
gc_malloc_allocated_size(VALUE self)
{
    return UINT2NUM(rb_objspace.malloc_params.allocated_size);
}
malloc_allocations → Integer 按一下以切換來源

傳回 malloc() 分配的次數。

僅在使用 CALC_EXACT_MALLOC_SIZE 建置 ruby 時才可用。

static VALUE
gc_malloc_allocations(VALUE self)
{
    return UINT2NUM(rb_objspace.malloc_params.allocations);
}
measure_total_time → true/false 按一下以切換來源

傳回 measure_total_time 旗標(預設值:true)。請注意,測量可能會影響應用程式的效能。

# File gc.rb, line 308
def self.measure_total_time
  Primitive.cexpr! %{
    RBOOL(rb_objspace.flags.measure_gc)
  }
end
measure_total_time = true/false 按一下以切換來源

啟用 GC 時間測量。您可以使用 GC.stat(:time) 取得結果。請注意,GC 時間測量可能會造成一些效能損耗。

# File gc.rb, line 296
def self.measure_total_time=(flag)
  Primitive.cstmt! %{
    rb_objspace.flags.measure_gc = RTEST(flag) ? TRUE : FALSE;
    return flag;
  }
end
remove_stress_to_class(class[, ...]) 按一下以切換來源

在配置給定類別的執行個體時,不再引發 NoMemoryError

static VALUE
rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self)
{
    rb_objspace_t *objspace = &rb_objspace;
    int i;

    if (stress_to_class) {
        for (i = 0; i < argc; ++i) {
            rb_ary_delete_same(stress_to_class, argv[i]);
        }
        if (RARRAY_LEN(stress_to_class) == 0) {
            set_stress_to_class(0);
        }
    }
    return Qnil;
}
start(full_mark: true, immediate_mark: true, immediate_sweep: true) 按一下以切換來源

啟動垃圾回收,即使手動停用。

full_mark 關鍵字引數決定是否執行主要垃圾回收週期。設定為 true 時,會執行主要垃圾回收週期,表示會標記所有物件。設定為 false 時,會執行次要垃圾回收週期,表示只會標記年輕物件。

immediate_mark 關鍵字引數決定是否執行增量標記。設定為 true 時,會在呼叫此方法期間完成標記。設定為 false 時,會分階段執行標記,與後續 Ruby 程式碼執行交錯,因此標記可能不會在此方法呼叫期間完成。請注意,如果 full_markfalse,則標記將永遠是立即的,與 immediate_mark 的值無關。

immedate_sweep 關鍵字引數決定是否延後清除 (使用延遲清除)。設定為 true 時,會分階段執行清除,與後續 Ruby 程式碼執行交錯,因此清除可能不會在此方法呼叫期間完成。設定為 false 時,會在呼叫此方法期間完成清除。

注意:這些關鍵字引數會依據實作和版本而異。它們無法保證與未來相容,如果基礎實作不支援它們,可能會被忽略。

# File gc.rb, line 38
def self.start full_mark: true, immediate_mark: true, immediate_sweep: true
  Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false
end
stat → Hash 按一下以切換來源
stat(hash) → Hash
stat(:key) → Numeric

傳回包含 GC 資訊的 Hash

雜湊的內容會依據實作而異,而且可能會在未來不經通知而變更。

雜湊包含 GC 的內部統計資訊,例如

count

自應用程式啟動以來執行的垃圾回收總數目 (count 包含次要和主要垃圾回收)

time

花在垃圾回收的總時間 (以毫秒為單位)

heap_allocated_pages

:heap_eden_pages + :heap_tomb_pages 的總頁數

heap_sorted_length

可以放入保留所有頁面參考的緩衝區的頁面數

heap_allocatable_pages

應用程式可以在沒有額外 GC 的情況下配置的總頁數

heap_available_slots

所有 :heap_allocated_pages 中的總插槽數

heap_live_slots

包含活動物件的總插槽數

heap_free_slots

不包含活動物件的總插槽數

heap_final_slots

具有待執行最終處理常式的總插槽數

heap_marked_slots

上次 GC 中標記的物件總數

heap_eden_pages

至少包含一個活動插槽的總頁數

heap_tomb_pages

不包含任何活動插槽的總頁數

total_allocated_pages

自應用程式啟動以來配置的累計頁數

total_freed_pages

自應用程式啟動以來釋放的累計頁數

total_allocated_objects

自應用程式啟動以來配置的累計物件數

total_freed_objects

自應用程式啟動以來釋放的累計物件數

malloc_increase_bytes

為物件在堆上配置的記憶體量。任何 GC 都會減少此值

malloc_increase_bytes_limit

:malloc_increase_bytes 超過此限制時,會觸發 GC

minor_gc_count

自處理程序啟動以來執行的垃圾收集次數

major_gc_count

自處理程序啟動以來執行的主要垃圾收集次數

compact_count

自處理程序啟動以來執行的壓縮次數

read_barrier_faults

在壓縮期間觸發讀取障礙的次數

total_moved_objects

壓縮已移動的物件總數

remembered_wb_unprotected_objects

沒有寫入障礙的物件總數

remembered_wb_unprotected_objects_limit

:remembered_wb_unprotected_objects 超過此限制時,會觸發主要 GC

old_objects

至少存活 3 次垃圾收集的活動舊物件數

old_objects_limit

:old_objects 超過此限制時,會觸發主要 GC

oldmalloc_increase_bytes

為物件分配在堆上的記憶體量。會因主要 GC 而減少

oldmalloc_increase_bytes_limit

:old_malloc_increase_bytes 超過此限制時,會觸發主要 GC

如果給定選用引數 hash,則會覆寫並傳回它。這是為了避免探測效應。

此方法預期只會在 CRuby 上運作。

# File gc.rb, line 189
def self.stat hash_or_key = nil
  Primitive.gc_stat hash_or_key
end
stat_heap → Hash 按一下以切換來源
stat_heap(nil, hash) → Hash
stat_heap(heap_name) → Hash
stat_heap(heap_name, hash) → Hash
stat_heap(heap_name, :key) → Numeric

傳回 GC 中堆的資訊。

如果傳入第一個選用引數 heap_name 且不為 nil,它會傳回包含特定堆資訊的 Hash。否則,它會傳回一個 Hash,其中堆名稱為鍵,而包含堆資訊的 Hash 為值。

如果傳入第二個選用引數 hash_or_key 作為 Hash,它會被覆寫並傳回。這是為了避免探測效應。

如果傳入兩個選用引數,且第二個選用引數為符號,它會傳回特定堆的 Numeric 值。

在 CRuby 中,heap_name 的型別為 Integer,但在其他實作中可能是 String 型別。

雜湊的內容會依據實作而異,而且可能會在未來不經通知而變更。

如果傳入選用引數 hash,它會被覆寫並傳回。

此方法預期只會在 CRuby 上運作。

hash 包含以下關於 GC 中內部資訊的鍵

slot_size

堆的槽位大小(以位元組為單位)。

heap_allocatable_pages

可以在不觸發新的垃圾回收週期的情況下配置的頁面數。

heap_eden_pages

伊甸園堆中的頁面數。

heap_eden_slots

伊甸園堆中所有頁面中的槽位總數。

heap_tomb_pages

墓園堆中的頁面數。墓園堆只包含不具有任何存活物件的頁面。

heap_tomb_slots

墓園堆中所有頁面中的槽位總數。

total_allocated_pages

已在堆中配置的頁面總數。

total_freed_pages

已在堆中釋放並回收到系統中的頁面總數。

force_major_gc_count

由於沒有可用插槽,此堆執行強制主要垃圾回收週期的次數。

force_incremental_marking_finish_count

由於沒有可用池插槽,此堆執行強制增量標記完成的次數。

# File gc.rb, line 252
def self.stat_heap heap_name = nil, hash_or_key = nil
  Primitive.gc_stat_heap heap_name, hash_or_key
end
stress → integer, true 或 false 按一下以切換原始碼

傳回 GC 壓力模式的目前狀態。

# File gc.rb, line 77
def self.stress
  Primitive.gc_stress_get
end
stress = flag → flag 按一下以切換原始碼

更新 GC 壓力模式。

當啟用壓力模式時,GC 會在每次 GC 機會中呼叫:所有記憶體和物件配置。

啟用壓力模式會降低效能,它只用於偵錯。

flag 可以是 true、false 或整數位元或下列旗標。

0x01:: no major GC
0x02:: no immediate sweep
0x04:: full mark after malloc/calloc/realloc
# File gc.rb, line 95
def self.stress=(flag)
  Primitive.gc_stress_set_m flag
end
total_time → int 按一下以切換原始碼

以奈秒為單位傳回測量的 GC 總時間。

# File gc.rb, line 318
def self.total_time
  Primitive.cexpr! %{
    ULL2NUM(rb_objspace.profile.marking_time_ns + rb_objspace.profile.sweeping_time_ns)
  }
end
verify_compaction_references(toward: nil, double_heap: false) → hash 按一下以切換原始碼

驗證壓縮參考一致性。

此方法是特定於實作的。在壓縮期間,已移動的物件會以 T_MOVED 物件取代。壓縮後,沒有物件應具有對 T_MOVED 物件的參考。

此函式會擴充堆積,以確保有空間移動所有物件,壓縮堆積以確保所有物件都移動,更新所有參考,然後執行完整 GC。如果任何物件包含對 T_MOVED 物件的參考,該物件應推入標記堆疊,並會產生 SEGV。

# File gc.rb, line 285
def self.verify_compaction_references(toward: nil, double_heap: false, expand_heap: false)
  Primitive.gc_verify_compaction_references(double_heap, expand_heap, toward == :empty)
end
verify_internal_consistency → nil 按一下以切換原始碼

驗證內部一致性。

此方法是特定於實作的。如果支援 RGenGC,此方法現在會檢查世代一致性。

static VALUE
gc_verify_internal_consistency_m(VALUE dummy)
{
    gc_verify_internal_consistency(&rb_objspace);
    return Qnil;
}

公開執行個體方法

garbage_collect(full_mark: true, immediate_mark: true, immediate_sweep: true) 按一下以切換原始碼

GC.start 的別名

# File gc.rb, line 43
def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true
  Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false
end