module ObjectSpace
objspace 库扩展了 ObjectSpace 模块,并添加了几个方法来获取有关对象/内存管理的内部统计信息。
您需要 require 'objspace' 才能使用此扩展模块。
通常,如果您不了解 MRI 实现,不应使用此库。此库主要面向需要了解 MRI 内存使用情况的(内存)分析器开发人员和 MRI 开发人员。
ObjectSpace 模块包含许多与垃圾回收机制交互的例程,并允许您通过迭代器遍历所有活动的(living)对象。
ObjectSpace 还支持对象 finalizer,这些 finalizer 在特定对象被垃圾回收销毁后会被调用。有关如何正确使用此方法的关键信息,请参阅 ObjectSpace.define_finalizer 的文档。
a = "A" b = "B" ObjectSpace.define_finalizer(a, proc {|id| puts "Finalizer one on #{id}" }) ObjectSpace.define_finalizer(b, proc {|id| puts "Finalizer two on #{id}" }) a = nil b = nil
产生
Finalizer two on 537763470 Finalizer one on 537763480
Public Class Methods
Source
static VALUE
allocation_class_path(VALUE self, VALUE obj)
{
struct allocation_info *info = lookup_allocation_info(obj);
if (info && info->class_path) {
return rb_str_new2(info->class_path);
}
else {
return Qnil;
}
}
返回给定 object 的类。
class A def foo ObjectSpace::trace_object_allocations do obj = Object.new p "#{ObjectSpace::allocation_class_path(obj)}" end end end A.new.foo #=> "Class"
有关更多信息和示例,请参阅 ::trace_object_allocations。
Source
static VALUE
allocation_generation(VALUE self, VALUE obj)
{
struct allocation_info *info = lookup_allocation_info(obj);
if (info) {
return SIZET2NUM(info->generation);
}
else {
return Qnil;
}
}
返回给定 object 的垃圾回收器代数。
class B include ObjectSpace def foo trace_object_allocations do obj = Object.new p "Generation is #{allocation_generation(obj)}" end end end B.new.foo #=> "Generation is 3"
有关更多信息和示例,请参阅 ::trace_object_allocations。
Source
static VALUE
allocation_method_id(VALUE self, VALUE obj)
{
struct allocation_info *info = lookup_allocation_info(obj);
if (info) {
return info->mid;
}
else {
return Qnil;
}
}
返回给定 object 的方法标识符。
class A include ObjectSpace def foo trace_object_allocations do obj = Object.new p "#{allocation_class_path(obj)}##{allocation_method_id(obj)}" end end end A.new.foo #=> "Class#new"
有关更多信息和示例,请参阅 ::trace_object_allocations。
Source
static VALUE
allocation_sourcefile(VALUE self, VALUE obj)
{
struct allocation_info *info = lookup_allocation_info(obj);
if (info && info->path) {
return rb_str_new2(info->path);
}
else {
return Qnil;
}
}
返回给定 object 的源文件来源。
有关更多信息和示例,请参阅 ::trace_object_allocations。
Source
static VALUE
allocation_sourceline(VALUE self, VALUE obj)
{
struct allocation_info *info = lookup_allocation_info(obj);
if (info) {
return INT2FIX(info->line);
}
else {
return Qnil;
}
}
返回给定 object 的源文件原始行号。
有关更多信息和示例,请参阅 ::trace_object_allocations。
Source
static VALUE
count_imemo_objects(int argc, VALUE *argv, VALUE self)
{
VALUE hash = setup_hash(argc, argv);
if (imemo_type_ids[0] == 0) {
#define INIT_IMEMO_TYPE_ID(n) (imemo_type_ids[n] = rb_intern_const(#n))
INIT_IMEMO_TYPE_ID(imemo_env);
INIT_IMEMO_TYPE_ID(imemo_cref);
INIT_IMEMO_TYPE_ID(imemo_svar);
INIT_IMEMO_TYPE_ID(imemo_throw_data);
INIT_IMEMO_TYPE_ID(imemo_ifunc);
INIT_IMEMO_TYPE_ID(imemo_memo);
INIT_IMEMO_TYPE_ID(imemo_ment);
INIT_IMEMO_TYPE_ID(imemo_iseq);
INIT_IMEMO_TYPE_ID(imemo_tmpbuf);
INIT_IMEMO_TYPE_ID(imemo_callinfo);
INIT_IMEMO_TYPE_ID(imemo_callcache);
INIT_IMEMO_TYPE_ID(imemo_constcache);
INIT_IMEMO_TYPE_ID(imemo_fields);
#undef INIT_IMEMO_TYPE_ID
}
each_object_with_flags(count_imemo_objects_i, (void *)hash);
return hash;
}
计算每种 T_IMEMO 类型的对象数量。
此方法仅供对 Ruby 程序性能和内存使用感兴趣的 MRI 开发人员使用。
它返回一个哈希,例如
{:imemo_ifunc=>8,
:imemo_svar=>7,
:imemo_cref=>509,
:imemo_memo=>1,
:imemo_throw_data=>1}
如果提供了可选参数 result_hash,则它将被覆盖并返回。这是为了避免探测效应。
返回哈希的内容是实现特定的,将来可能会更改。
在此版本中,键是符号对象。
此方法预计仅在 C Ruby 上工作。
Source
static VALUE
count_nodes(int argc, VALUE *argv, VALUE os)
{
return setup_hash(argc, argv);
}
计算每种节点类型的节点数量。
此方法仅供对 Ruby 程序性能和内存使用感兴趣的 MRI 开发人员使用。
它返回一个哈希,例如
{:NODE_METHOD=>2027, :NODE_FBODY=>1927, :NODE_CFUNC=>1798, ...}
如果提供了可选参数 result_hash,则它将被覆盖并返回。这是为了避免探测效应。
注意:返回哈希的内容是实现定义的。它可能会在将来更改。
此方法预计仅在 C Ruby 上工作。
Source
static VALUE
count_objects(int argc, VALUE *argv, VALUE os)
{
struct count_objects_data data = { 0 };
VALUE hash = Qnil;
VALUE types[T_MASK + 1];
if (rb_check_arity(argc, 0, 1) == 1) {
hash = argv[0];
if (!RB_TYPE_P(hash, T_HASH))
rb_raise(rb_eTypeError, "non-hash given");
}
for (size_t i = 0; i <= T_MASK; i++) {
// type_sym can allocate an object,
// so we need to create all key symbols in advance
// not to disturb the result
types[i] = type_sym(i);
}
// Same as type_sym, we need to create all key symbols in advance
VALUE total = ID2SYM(rb_intern("TOTAL"));
VALUE free = ID2SYM(rb_intern("FREE"));
rb_gc_impl_each_object(rb_gc_get_objspace(), count_objects_i, &data);
if (NIL_P(hash)) {
hash = rb_hash_new();
}
else if (!RHASH_EMPTY_P(hash)) {
rb_hash_stlike_foreach(hash, set_zero, hash);
}
rb_hash_aset(hash, total, SIZET2NUM(data.total));
rb_hash_aset(hash, free, SIZET2NUM(data.freed));
for (size_t i = 0; i <= T_MASK; i++) {
if (data.counts[i]) {
rb_hash_aset(hash, types[i], SIZET2NUM(data.counts[i]));
}
}
return hash;
}
按类型计算所有对象数量。
它返回一个哈希,例如
{
:TOTAL=>10000,
:FREE=>3011,
:T_OBJECT=>6,
:T_CLASS=>404,
# ...
}
返回哈希的内容是实现特定的。它可能会在将来更改。
以 :T_ 开头的键表示活动对象。例如,:T_ARRAY 是数组的数量。:FREE 表示当前未使用的对象槽。:TOTAL 表示上述的总和。
如果提供了可选参数 result_hash,则它将被覆盖并返回。这是为了避免探测效应。
h = {} ObjectSpace.count_objects(h) puts h # => { :TOTAL=>10000, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249 }
此方法预计仅在 C Ruby 上工作。
Source
static VALUE
count_objects_size(int argc, VALUE *argv, VALUE os)
{
size_t counts[T_MASK+1];
size_t total = 0;
enum ruby_value_type i;
VALUE hash = setup_hash(argc, argv);
for (i = 0; i <= T_MASK; i++) {
counts[i] = 0;
}
each_object_with_flags(cos_i, &counts[0]);
for (i = 0; i <= T_MASK; i++) {
if (counts[i]) {
VALUE type = type2sym(i);
total += counts[i];
rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
}
}
rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
return hash;
}
计算每种类型的对象大小(以字节为单位)。
请注意,此信息不完整。您应将此信息视为仅作为提示。特别是 T_DATA 的总大小可能不正确。
它返回一个哈希,例如
{:TOTAL=>1461154, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249, ...}
如果提供了可选参数 result_hash,则它将被覆盖并返回。这是为了避免探测效应。
返回哈希的内容是实现定义的。它可能会在将来更改。
此方法预计仅在 C Ruby 上工作。
Source
static VALUE
count_symbols(int argc, VALUE *argv, VALUE os)
{
struct dynamic_symbol_counts dynamic_counts = {0, 0};
VALUE hash = setup_hash(argc, argv);
size_t immortal_symbols = rb_sym_immortal_count();
each_object_with_flags(cs_i, &dynamic_counts);
rb_hash_aset(hash, ID2SYM(rb_intern("mortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.mortal));
rb_hash_aset(hash, ID2SYM(rb_intern("immortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.immortal));
rb_hash_aset(hash, ID2SYM(rb_intern("immortal_static_symbol")), SIZET2NUM(immortal_symbols - dynamic_counts.immortal));
rb_hash_aset(hash, ID2SYM(rb_intern("immortal_symbol")), SIZET2NUM(immortal_symbols));
return hash;
}
计算每种 Symbol 类型的符号数量。
此方法仅供对 Ruby 程序性能和内存使用感兴趣的 MRI 开发人员使用。
如果提供了可选参数 result_hash,则它将被覆盖并返回。这是为了避免探测效应。
注意:返回哈希的内容是实现定义的。它可能会在将来更改。
此方法预计仅在 C Ruby 上工作。
在此版本的 MRI 中,有 3 种类型的符号(以及 1 个总计数)。
* mortal_dynamic_symbol: GC target symbols (collected by GC) * immortal_dynamic_symbol: Immortal symbols promoted from dynamic symbols (do not collected by GC) * immortal_static_symbol: Immortal symbols (do not collected by GC) * immortal_symbol: total immortal symbols (immortal_dynamic_symbol+immortal_static_symbol)
Source
static VALUE
count_tdata_objects(int argc, VALUE *argv, VALUE self)
{
VALUE hash = setup_hash(argc, argv);
each_object_with_flags(cto_i, (void *)hash);
return hash;
}
计算每种 T_DATA 类型的对象数量。
此方法仅供对 Ruby 程序性能和内存使用感兴趣的 MRI 开发人员使用。
它返回一个哈希,例如
{RubyVM::InstructionSequence=>504, :parser=>5, :barrier=>6,
:mutex=>6, Proc=>60, RubyVM::Env=>57, Mutex=>1, Encoding=>99,
ThreadGroup=>1, Binding=>1, Thread=>1, RubyVM=>1, :iseq=>1,
Random=>1, ARGF.class=>1, Data=>1, :autoload=>3, Time=>2}
# T_DATA objects existing at startup on r32276.
如果提供了可选参数 result_hash,则它将被覆盖并返回。这是为了避免探测效应。
返回哈希的内容是实现特定的,将来可能会更改。
在此版本中,键是 Class 对象或 Symbol 对象。
如果对象是普通(可访问)对象的类型,则键是 Class 对象。如果对象不是普通(内部)对象的类型,则键是由 rb_data_type_struct 注册的符号名称。
此方法预计仅在 C Ruby 上工作。
Source
static VALUE
define_final(int argc, VALUE *argv, VALUE os)
{
VALUE obj, block;
rb_scan_args(argc, argv, "11", &obj, &block);
if (argc == 1) {
block = rb_block_proc();
}
if (rb_callable_receiver(block) == obj) {
rb_warn("finalizer references object to be finalized");
}
return rb_define_finalizer(obj, block);
}
将 aProc 添加为 finalizer,在 obj 被销毁后调用。obj 的对象 ID 将作为参数传递给 aProc。如果 aProc 是 lambda 或方法,请确保它可以接受单个参数。
返回值是一个数组 [0, aProc]。
推荐的两种模式是:要么在非实例方法中创建 finalizer proc,这样它可以安全地捕获所需状态,要么使用自定义的可调用对象,该对象将所需状态显式存储为实例变量。
class Foo def initialize(data_needed_for_finalization) ObjectSpace.define_finalizer(self, self.class.create_finalizer(data_needed_for_finalization)) end def self.create_finalizer(data_needed_for_finalization) proc { puts "finalizing #{data_needed_for_finalization}" } end end class Bar class Remover def initialize(data_needed_for_finalization) @data_needed_for_finalization = data_needed_for_finalization end def call(id) puts "finalizing #{@data_needed_for_finalization}" end end def initialize(data_needed_for_finalization) ObjectSpace.define_finalizer(self, Remover.new(data_needed_for_finalization)) end end
请注意,如果您的 finalizer 引用了要 finalizer 的对象,它将永远不会在 GC 上运行,尽管它仍然会在退出时运行。如果您将要 finalizer 的对象捕获为 finalizer 的接收者,您将收到警告。
class CapturesSelf def initialize(name) ObjectSpace.define_finalizer(self, proc { # this finalizer will only be run on exit puts "finalizing #{name}" }) end end
另请注意,finalization 可能不可预测,并且除了退出时之外,永远不能保证会运行。
Source
static VALUE
os_each_obj(int argc, VALUE *argv, VALUE os)
{
VALUE of;
of = (!rb_check_arity(argc, 0, 1) ? 0 : argv[0]);
RETURN_ENUMERATOR(os, 1, &of);
return os_obj_of(of);
}
对本 Ruby 进程中的每个活动、非立即对象调用一次块。如果指定了 module,则仅对匹配(或为子类)module 的类或模块调用块。返回找到的对象数量。立即对象(如 Fixnums、静态 Symbols true、false 和 nil)永远不会被返回。
如果没有给出块,则返回一个迭代器。
Job = Class.new jobs = [Job.new, Job.new] count = ObjectSpace.each_object(Job) {|x| p x } puts "Total count: #{count}"
产生
#<Job:0x000000011d6cbbf0> #<Job:0x000000011d6cbc68> Total count: 2
由于当前 Ractor 实现中的一个问题,当进程处于多 Ractor 模式时,此方法不会产生 Ractor 不可共享的对象。当首次调用 Ractor.new 时,多 Ractor 模式会被启用。有关更多信息,请参阅 bugs.ruby-lang.org/issues/19387。
a = 12345678987654321 # shareable b = [].freeze # shareable c = {} # not shareable ObjectSpace.each_object {|x| x } # yields a, b, and c Ractor.new {} # enter multi-Ractor mode ObjectSpace.each_object {|x| x } # does not yield c
Source
# File gc.rb, line 594 def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false end
GC.start 的别名。
Source
static VALUE
objspace_internal_class_of(VALUE self, VALUE obj)
{
VALUE klass;
if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
obj = (VALUE)DATA_PTR(obj);
}
if (RB_TYPE_P(obj, T_IMEMO)) {
return Qnil;
}
else {
klass = CLASS_OF(obj);
return wrap_klass_iow(klass);
}
}
Source
static VALUE
objspace_internal_super_of(VALUE self, VALUE obj)
{
VALUE super;
if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
obj = (VALUE)DATA_PTR(obj);
}
switch (OBJ_BUILTIN_TYPE(obj)) {
case T_MODULE:
case T_CLASS:
case T_ICLASS:
super = rb_class_super_of(obj);
break;
default:
rb_raise(rb_eArgError, "class or module is expected");
}
return wrap_klass_iow(super);
}
Source
static VALUE
memsize_of_m(VALUE self, VALUE obj)
{
return SIZET2NUM(rb_obj_memsize_of(obj));
}
返回 obj 占用的内存大小(以字节为单位)。
请注意,返回的大小不完整。您应将此信息视为仅作为提示。特别是 T_DATA 的大小可能不正确。
此方法预计仅在 CRuby 上工作。
从 Ruby 3.2 开始,使用可变宽度分配,它会返回实际使用的槽大小以及在槽外部分配的任何额外内存(如外部字符串、数组或哈希表)。
Source
static VALUE
memsize_of_all_m(int argc, VALUE *argv, VALUE self)
{
struct total_data data = {0, 0};
if (argc > 0) {
rb_scan_args(argc, argv, "01", &data.klass);
}
each_object_with_flags(total_i, &data);
return SIZET2NUM(data.total);
}
返回所有活动对象占用的内存大小(以字节为单位)。
如果提供了 klass(应为 Class 对象),则返回给定类的实例的总内存大小。
请注意,返回的大小不完整。您应将此信息视为仅作为提示。特别是 T_DATA 的大小可能不正确。
请注意,此方法不返回总的 malloc 分配的内存大小。
此方法可以通过以下 Ruby 代码定义
def memsize_of_all klass = false total = 0 ObjectSpace.each_object{|e| total += ObjectSpace.memsize_of(e) if klass == false || e.kind_of?(klass) } total end
此方法预计仅在 C Ruby 上工作。
Source
static VALUE
reachable_objects_from(VALUE self, VALUE obj)
{
if (!RB_SPECIAL_CONST_P(obj)) {
struct rof_data data;
if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
obj = (VALUE)DATA_PTR(obj);
}
data.refs = rb_obj_hide(rb_ident_hash_new());
data.values = rb_ary_new();
rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data);
return data.values;
}
else {
return Qnil;
}
}
- MRI 特有功能。
-
返回从“obj”可达的所有对象。
此方法返回从“obj”可达的所有对象。
如果“obj”对同一个对象“x”有两个或更多引用,则返回的数组只包含一个“x”对象。
如果“obj”是一个不可标记(非堆管理)对象,如 true、false、nil、symbols 和 Fixnums(以及 Flonum),则它只返回 nil。
如果“obj”引用了内部对象,则它返回 ObjectSpace::InternalObjectWrapper 类的实例。此对象包含对内部对象的引用,您可以使用“type”方法检查内部对象的类型。
如果“obj”是 ObjectSpace::InternalObjectWrapper 类的实例,则此方法返回从“obj”指向的内部对象可达的所有对象。
使用此方法,您可以查找内存泄漏。
此方法预计仅在 C Ruby 上工作。
示例
ObjectSpace.reachable_objects_from(['a', 'b', 'c']) #=> [Array, 'a', 'b', 'c'] ObjectSpace.reachable_objects_from(['a', 'a', 'a']) #=> [Array, 'a', 'a', 'a'] # all 'a' strings have different object id ObjectSpace.reachable_objects_from([v = 'a', v, v]) #=> [Array, 'a'] ObjectSpace.reachable_objects_from(1) #=> nil # 1 is not markable (heap managed) object
Source
static VALUE
reachable_objects_from_root(VALUE self)
{
struct rofr_data data;
VALUE hash = data.categories = rb_ident_hash_new();
data.last_category = 0;
rb_objspace_reachable_objects_from_root(reachable_object_from_root_i, &data);
rb_hash_foreach(hash, collect_values_of_values, hash);
return hash;
}
- MRI 特有功能。
-
返回从根可达的所有对象。
Source
static VALUE
trace_object_allocations(VALUE self)
{
trace_object_allocations_start(self);
return rb_ensure(rb_yield, Qnil, trace_object_allocations_stop, self);
}
从 ObjectSpace 扩展模块开始跟踪对象分配。
例如
require 'objspace' class C include ObjectSpace def foo trace_object_allocations do obj = Object.new p "#{allocation_sourcefile(obj)}:#{allocation_sourceline(obj)}" end end end C.new.foo #=> "objtrace.rb:8"
此示例已包含 ObjectSpace 模块,以便于阅读,但您也可以使用 ::trace_object_allocations 符号(推荐)。
请注意,此功能会带来巨大的性能下降和巨大的内存消耗。
Source
static VALUE
trace_object_allocations_clear(VALUE self)
{
struct traceobj_arg *arg = get_traceobj_arg();
/* clear tables */
st_foreach(arg->object_table, free_values_i, 0);
st_clear(arg->object_table);
st_foreach(arg->str_table, free_keys_i, 0);
st_clear(arg->str_table);
/* do not touch TracePoints */
return Qnil;
}
清除记录的跟踪信息。
Source
static VALUE
trace_object_allocations_debug_start(VALUE self)
{
tmp_keep_remains = 1;
if (object_allocations_reporter_registered == 0) {
object_allocations_reporter_registered = 1;
rb_bug_reporter_add(object_allocations_reporter, 0);
}
return trace_object_allocations_start(self);
}
开始跟踪对象的分配以进行 GC 调试。如果您在应用程序中遇到 BUG “... is T_NONE”(等等),请尝试在此方法处开始使用您的应用程序。
Source
static VALUE
trace_object_allocations_start(VALUE self)
{
struct traceobj_arg *arg = get_traceobj_arg();
if (arg->running++ > 0) {
/* do nothing */
}
else {
if (arg->newobj_trace == 0) {
arg->newobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, newobj_i, arg);
arg->freeobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_FREEOBJ, freeobj_i, arg);
}
rb_tracepoint_enable(arg->newobj_trace);
rb_tracepoint_enable(arg->freeobj_trace);
}
return Qnil;
}
开始跟踪对象分配。
Source
static VALUE
trace_object_allocations_stop(VALUE self)
{
struct traceobj_arg *arg = get_traceobj_arg();
if (arg->running > 0) {
arg->running--;
}
if (arg->running == 0) {
if (arg->newobj_trace != 0) {
rb_tracepoint_disable(arg->newobj_trace);
}
if (arg->freeobj_trace != 0) {
rb_tracepoint_disable(arg->freeobj_trace);
}
}
return Qnil;
}
停止跟踪对象分配。
请注意,如果调用了 ::trace_object_allocations_start n 次,则在调用 ::trace_object_allocations_stop n 次之后,跟踪才会停止。
Source
static VALUE
undefine_final(VALUE os, VALUE obj)
{
return rb_undefine_finalizer(obj);
}
移除 obj 的所有 finalizer。
Public Instance Methods
Source
# File ext/objspace/lib/objspace.rb, line 28 def dump(obj, output: :string) out = case output when :file, nil require 'tempfile' Tempfile.create(%w(rubyobj .json)) when :stdout STDOUT when :string +'' when IO output else raise ArgumentError, "wrong output option: #{output.inspect}" end ret = _dump(obj, out) return nil if output == :stdout ret end
Source
# File ext/objspace/lib/objspace.rb, line 84 def dump_all(output: :file, full: false, since: nil, shapes: true) out = case output when :file, nil require 'tempfile' Tempfile.create(%w(rubyheap .json)) when :stdout STDOUT when :string +'' when IO output else raise ArgumentError, "wrong output option: #{output.inspect}" end shapes = 0 if shapes == true ret = _dump_all(out, full, since, shapes) return nil if output == :stdout ret end
将 Ruby 堆的内容转储为 JSON 格式。
output 参数与 dump 中的相同。
full 必须为布尔值。如果为 true,则转储所有堆槽,包括空槽(T_NONE)。
since 必须是一个非负整数或 nil。
如果 since 是正整数,则只转储该代及更新代中的对象。当前代可以通过 GC::count 访问。没有启用对象分配跟踪的对象将被忽略。有关更多信息和示例,请参阅 ::trace_object_allocations。
如果 since 被省略或为 nil,则转储所有对象。
shapes 必须为布尔值或非负整数。
如果 shapes 是正整数,则只转储比提供的 shape id 新的 shape。当前 shape_id 可以通过 RubyVM.stat(:next_shape_id) 访问。
如果 shapes 为 false,则不转储任何 shape。
要仅转储在特定时间点之后分配的对象,您可以组合使用 since 和 shapes。
ObjectSpace.trace_object_allocations GC.start gc_generation = GC.count shape_generation = RubyVM.stat(:next_shape_id) call_method_to_instrument ObjectSpace.dump_all(since: gc_generation, shapes: shape_generation)
此方法预计仅在 C Ruby 上工作。这是一个实验性方法,可能会发生更改。特别是,函数签名和输出格式在新版本的 ruby 中不一定兼容。
Source
# File ext/objspace/lib/objspace.rb, line 116 def dump_shapes(output: :file, since: 0) out = case output when :file, nil require 'tempfile' Tempfile.create(%w(rubyshapes .json)) when :stdout STDOUT when :string +'' when IO output else raise ArgumentError, "wrong output option: #{output.inspect}" end ret = _dump_shapes(out, since) return nil if output == :stdout ret end
私有实例方法
Source
# File gc.rb, line 594 def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false end
GC.start 的别名。