模块 GC

GC 模块为 Ruby 的标记清除垃圾回收机制提供了一个接口。

一些底层方法也可以通过 ObjectSpace 模块访问。

您可以通过 GC::Profiler 获取有关 GC 操作的信息。

公共类方法

config → 哈希 点击切换源代码
config(哈希) → 哈希

设置或获取有关当前 GC 配置的信息。

配置参数特定于 GC 实现,可能会在不通知的情况下更改。

此方法可以不带参数调用,以检索当前配置,作为带有 Symbol 键的 Hash

此方法也可以使用 Hash 参数调用,以将值分配给有效的配置键。传递的 Hash 中缺少的配置键将保持不变。

如果将一个不对应于正在使用的 GC 实现的有效配置键的键/值对传递给此函数,则不会更新任何配置,该键将出现在返回的 Hash 中,其值将为 nil。这是为了方便在 GC 实现之间轻松迁移。

在两种调用序列中,GC.config 的返回值都将是一个 Hash,其中包含最新的完整配置,即特定 GC 实现定义的所有键和值。在配置更新的情况下,返回值将包括正在更新的新值。

此方法预计仅在 CRuby 上有效。

GC 实现无关的值

GC.config 哈希还可以包含全局且只读的键。这些键不特定于任何一个 GC 库实现,尝试写入它们将引发 ArgumentError

当前只有一个全局只读键

实现

返回一个 String,其中包含当前加载的 GC 库的名称(如果已使用 RUBY_GC_LIBRARY 加载),否则返回“default”

GC 实现特定的值

GC 库应该记录自己的配置。Ruby 默认 GC 实现的有效键是

rgengc_allow_full_mark

控制是否允许 GC 运行完全标记(年轻和旧对象)。

当为 true 时,GC 会交错进行主要和次要的回收。这是默认设置。GC 将按预期运行。

当为 false 时,除非用户代码显式请求,否则 GC 永远不会触发完全标记循环。相反,只会运行次要标记——只会标记年轻对象。当堆空间耗尽时,将立即分配新页面,而不是运行完全标记。

将设置一个标志来通知已请求完全标记。可以使用 GC.latest_gc_info(:needs_major_by) 访问此标志

用户可以随时使用 GC.start(full_mark: true) 触发主要回收

当为 false 时,禁用从年轻到旧对象的提升。出于性能原因,建议在将此参数设置为 false 之前使用 Process.warmup 预热应用程序。

# File ruby_3_4_1/gc.rb, line 318
def self.config hash = nil
  return Primitive.gc_config_get unless hash

  if(Primitive.cexpr!("RBOOL(RB_TYPE_P(hash, T_HASH))"))
    if hash.include?(:implementation)
      raise ArgumentError, 'Attempting to set read-only key "Implementation"'
    end

    Primitive.gc_config_set hash
  else
    raise ArgumentError
  end
end
count → Integer 点击切换源代码

返回自进程启动以来发生 GC 的次数。

# File ruby_3_4_1/gc.rb, line 100
def self.count
  Primitive.gc_count
end
disable → true 或 false 点击切换源代码

禁用垃圾回收,如果垃圾回收已禁用,则返回 true

GC.disable   #=> false
GC.disable   #=> true
# File ruby_3_4_1/gc.rb, line 66
def self.disable
  Primitive.gc_disable
end
enable → true 或 false 点击切换源代码

启用垃圾回收,如果先前禁用垃圾回收,则返回 true

GC.disable   #=> false
GC.enable    #=> true
GC.enable    #=> false
# File ruby_3_4_1/gc.rb, line 54
def self.enable
  Primitive.gc_enable
end
latest_gc_info → 哈希 点击切换源代码
latest_gc_info(哈希) → 哈希
latest_gc_info(键) → 值

返回有关最近垃圾回收的信息。

如果给定的参数 hash 是一个 Hash 对象,则它会被覆盖并返回。这是为了避免探针效应。

如果给定的参数 key 是一个 Symbol 对象,则它返回与该键关联的值。这等效于 GC.latest_gc_info[key]

# File ruby_3_4_1/gc.rb, line 346
def self.latest_gc_info hash_or_key = nil
  if hash_or_key == nil
    hash_or_key = {}
  elsif Primitive.cexpr!("RBOOL(!SYMBOL_P(hash_or_key) && !RB_TYPE_P(hash_or_key, T_HASH))")
    raise TypeError, "non-hash or symbol given"
  end

  Primitive.cstmt! %{
    return rb_gc_latest_gc_info(hash_or_key);
  }
end
measure_total_time → true/false 点击切换源代码

返回 measure_total_time 标志(默认值:true)。请注意,测量可能会影响应用程序的性能。

# File ruby_3_4_1/gc.rb, line 376
def self.measure_total_time
  Primitive.cexpr! %{
    RBOOL(rb_gc_impl_get_measure_total_time(rb_gc_get_objspace()))
  }
end
measure_total_time = true/false 点击切换源代码

启用测量 GC 时间。您可以使用 GC.stat(:time) 获取结果。请注意,GC 时间测量可能会导致一些性能开销。

# File ruby_3_4_1/gc.rb, line 364
def self.measure_total_time=(flag)
  Primitive.cstmt! %{
    rb_gc_impl_set_measure_total_time(rb_gc_get_objspace(), flag);
    return flag;
  }
end
start(full_mark: true, immediate_mark: true, immediate_sweep: true) 点击切换源代码

启动垃圾回收,即使手动禁用也是如此。

full_mark 关键字参数确定是否执行主要垃圾回收循环。设置为 true 时,将运行主要垃圾回收循环,这意味着将标记所有对象。设置为 false 时,将运行次要垃圾回收循环,这意味着仅标记年轻对象。

immediate_mark 关键字参数确定是否执行增量标记。设置为 true 时,标记会在调用此方法期间完成。设置为 false 时,标记会分步骤执行,与未来的 Ruby 代码执行交错,因此标记可能不会在此方法调用期间完成。请注意,如果 full_markfalse,则无论 immediate_mark 的值如何,标记都将始终是即时的。

immediate_sweep 关键字参数确定是否延迟扫描(使用延迟扫描)。设置为 false 时,扫描会分步骤执行,与未来的 Ruby 代码执行交错,因此扫描可能不会在此方法调用期间完成。设置为 true 时,扫描会在调用此方法期间完成。

注意:这些关键字参数依赖于实现和版本。不能保证它们在未来兼容,如果底层实现不支持,则可能会被忽略。

# File ruby_3_4_1/gc.rb, line 35
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 → 哈希 点击切换源代码
stat(哈希) → 哈希
stat(:key) → 数字

返回一个 Hash,其中包含有关 GC 的信息。

哈希的内容特定于实现,可能会在未来更改,恕不另行通知。

哈希包含有关 GC 的内部统计信息,例如

计数

自应用程序启动以来运行的垃圾回收总数(计数包括次要和主要垃圾回收)

时间

在垃圾回收中花费的总时间(以毫秒为单位)

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

:oldmalloc_increase_bytes 超过此限制时,将触发主要 GC

如果给定可选参数哈希,则会覆盖并返回它。这是为了避免探针效应。

此方法预计仅在 CRuby 上有效。

# File ruby_3_4_1/gc.rb, line 184
def self.stat hash_or_key = nil
  Primitive.gc_stat hash_or_key
end
stat_heap → 哈希 点击切换源代码
stat_heap(nil, 哈希) → 哈希
stat_heap(heap_name) → 哈希
stat_heap(heap_name, 哈希) → 哈希
stat_heap(heap_name, :key) → 数字

返回 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_slots

伊甸园堆中所有页的总槽数。

heap_tomb_pages

墓地堆中的页数。墓地堆仅包含没有任何活动对象的页面。

heap_tomb_slots

墓地堆中所有页的总槽数。

total_allocated_pages

堆中已分配的总页数。

total_freed_pages

堆中已释放并返回给系统的总页数。

force_major_gc_count

由于空闲槽耗尽,此堆已强制启动主垃圾回收周期的次数。

force_incremental_marking_finish_count

由于池化槽耗尽,此堆已强制完成增量标记的次数。

# File ruby_3_4_1/gc.rb, line 247
def self.stat_heap heap_name = nil, hash_or_key = nil
  Primitive.gc_stat_heap heap_name, hash_or_key
end
stress → integer, true, or false 点击切换源

返回 GC 压力模式的当前状态。

# File ruby_3_4_1/gc.rb, line 74
def self.stress
  Primitive.gc_stress_get
end
stress = flag → flag 点击切换源

更新 GC 压力模式。

当启用压力模式时,GC 会在每个 GC 机会时被调用:所有内存和对象分配。

启用压力模式会降低性能;它仅用于调试。

标志可以是 true、false 或与以下标志按位或运算的整数

0x01:: no major GC
0x02:: no immediate sweep
0x04:: full mark after malloc/calloc/realloc
# File ruby_3_4_1/gc.rb, line 92
def self.stress=(flag)
  Primitive.gc_stress_set_m flag
end
total_time → int 点击切换源

以纳秒为单位返回测量的 GC 总时间。

# File ruby_3_4_1/gc.rb, line 386
def self.total_time
  Primitive.cexpr! %{
    ULL2NUM(rb_gc_impl_get_total_time(rb_gc_get_objspace()))
  }
end

公共实例方法

garbage_collect(full_mark: true, immediate_mark: true, immediate_sweep: true) 点击切换源

GC.start的别名

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