GC 模組
GC 模組提供介面給 Ruby 的標記和清除垃圾收集機制。
部分底層方法也可以透過 ObjectSpace
模組取得。
你可以透過 GC::Profiler
取得 GC 執行資訊。
常數
- INTERNAL_CONSTANTS
垃圾收集器的內部常數。
- OPTS
GC 建置選項
公開類別方法
在配置給定類別的執行個體時引發 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; }
傳回是否已啟用自動壓縮。
static VALUE gc_get_auto_compact(VALUE _) { return RBOOL(ruby_enable_autocompact); }
更新自動壓縮模式。
啟用時,壓縮器會在每個主要收集時執行。
啟用壓縮會降低主要收集的效能。
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; }
此函式會將 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); }
GC 執行次數。
它會傳回自程序啟動以來 GC 執行的次數。
# File gc.rb, line 105 def self.count Primitive.gc_count end
停用垃圾回收,如果垃圾回收已停用,則傳回 true
。
GC.disable #=> false GC.disable #=> true
# File gc.rb, line 69 def self.disable Primitive.gc_disable end
啟用垃圾回收,如果垃圾回收先前已停用,則傳回 true
。
GC.disable #=> false GC.enable #=> true GC.enable #=> false
# File gc.rb, line 57 def self.enable Primitive.gc_enable end
傳回最近一次 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; }
傳回最近一次垃圾回收的資訊。
如果給定選用引數 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() 分配的記憶體大小。
僅在使用 CALC_EXACT_MALLOC_SIZE
建置 ruby 時才可用。
static VALUE gc_malloc_allocated_size(VALUE self) { return UINT2NUM(rb_objspace.malloc_params.allocated_size); }
傳回 malloc() 分配的次數。
僅在使用 CALC_EXACT_MALLOC_SIZE
建置 ruby 時才可用。
static VALUE gc_malloc_allocations(VALUE self) { return UINT2NUM(rb_objspace.malloc_params.allocations); }
傳回 measure_total_time
旗標(預設值:true
)。請注意,測量可能會影響應用程式的效能。
# File gc.rb, line 308 def self.measure_total_time Primitive.cexpr! %{ RBOOL(rb_objspace.flags.measure_gc) } end
啟用 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
在配置給定類別的執行個體時,不再引發 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; }
啟動垃圾回收,即使手動停用。
full_mark
關鍵字引數決定是否執行主要垃圾回收週期。設定為 true
時,會執行主要垃圾回收週期,表示會標記所有物件。設定為 false
時,會執行次要垃圾回收週期,表示只會標記年輕物件。
immediate_mark
關鍵字引數決定是否執行增量標記。設定為 true
時,會在呼叫此方法期間完成標記。設定為 false
時,會分階段執行標記,與後續 Ruby 程式碼執行交錯,因此標記可能不會在此方法呼叫期間完成。請注意,如果 full_mark
為 false
,則標記將永遠是立即的,與 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
傳回包含 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
傳回 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
傳回 GC 壓力模式的目前狀態。
# File gc.rb, line 77 def self.stress Primitive.gc_stress_get end
更新 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
以奈秒為單位傳回測量的 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
驗證壓縮參考一致性。
此方法是特定於實作的。在壓縮期間,已移動的物件會以 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
驗證內部一致性。
此方法是特定於實作的。如果支援 RGenGC,此方法現在會檢查世代一致性。
static VALUE gc_verify_internal_consistency_m(VALUE dummy) { gc_verify_internal_consistency(&rb_objspace); return Qnil; }
公開執行個體方法
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