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 压缩中移动的对象的信息。
返回的哈希有两个键::considered 和 :moved。:considered 的哈希列出了压缩器考虑移动的对象数,而 :moved 的哈希列出了实际移动的对象数。有些对象无法移动(可能它们被固定),因此可以使用这些数字来计算压缩效率。
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; }
返回有关最近的垃圾回收的信息。
如果给出了可选参数哈希,则会覆盖它并返回它。这旨在避免探测效应。
# 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
如果给出了可选参数哈希,则会覆盖它并返回它。这旨在避免探测效应。
此方法仅适用于 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。
该哈希包含有关 GC 中内部信息的以下键
- slot_size
-
堆的槽大小(以字节为单位)。
- heap_allocatable_pages
-
heap_eden_pages
- heap_eden_pages
-
可以在不触发新的垃圾回收周期的情况下分配的页面数。
- eden 堆中的页面数。
-
heap_eden_slots
- heap_tomb_pages
-
eden 堆中所有页面中的槽总数。
- tomb 堆中的页面数。tomb 堆仅包含没有任何活动对象的页面。
-
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 机会(所有内存和对象分配)时调用。
启用压力模式会降低性能,它仅用于调试。
标志可以是 true、false 或与以下标志进行按位 OR 的整数。
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