Ruby 2.4

ObjectSpace

module ObjectSpace

objspace库扩展了ObjectSpace模块并添加了几个方法来获取有关对象/内存管理的内部统计信息。

你需要require 'objspace'使用这个扩展模块。

一般来说,如果您不了解MRI的实施情况,您*不应该使用这个库。主要的是,这个库用于需要了解MRI内存使用情况的(内存)探查器开发人员和MRI开发人员。

ObjectSpace模块包含许多与垃圾收集工具交互的例程,并允许您用迭代器遍历所有活动对象。

ObjectSpace还为对象终结器提供支持,当特定对象即将被垃圾收集销毁时,将会调用这些过程。

require 'objspace' 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}" })

生产:

Finalizer two on 537763470 Finalizer one on 537763480

公共类方法

_id2ref(object_id) → an_object Show source

将对象ID转换为对象的引用。不能在作为参数传递给终结器的对象id上调用。

s = "I am a string" #=> "I am a string" r = ObjectSpace._id2ref(s.object_id) #=> "I am a string" r == s #=> true

static VALUE id2ref(VALUE obj, VALUE objid) { #if SIZEOF_LONG == SIZEOF_VOIDP #define NUM2PTR(x) NUM2ULONG(x) #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP #define NUM2PTR(x) NUM2ULL(x) #endif rb_objspace_t *objspace = &rb_objspace; VALUE ptr; void *p0; ptr = NUM2PTR(objid p0 = (void *)ptr; if (ptr == Qtrue) return Qtrue; if (ptr == Qfalse) return Qfalse; if (ptr == Qnil) return Qnil; if (FIXNUM_P(ptr)) return (VALUE)ptr; if (FLONUM_P(ptr)) return (VALUE)ptr; ptr = obj_id_to_ref(objid if ((ptr % sizeof(RVALUE)) == (4 << 2)) { ID symid = ptr / sizeof(RVALUE if (rb_id2str(symid) == 0) rb_raise(rb_eRangeError, "%p is not symbol id value", p0 return ID2SYM(symid } if (!is_id_value(objspace, ptr)) { rb_raise(rb_eRangeError, "%p is not id value", p0 } if (!is_live_object(objspace, ptr)) { rb_raise(rb_eRangeError, "%p is recycled object", p0 } if (RBASIC(ptr)->klass == 0) { rb_raise(rb_eRangeError, "%p is internal object", p0 } return (VALUE)ptr; }

allocation_class_path(object) → string Show source

返回给定的类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。

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; } }

allocation_generation(object) → integer or nil Show source

返回给定的垃圾回收器生成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。

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; } }

allocation_method_id(object) → string Show source

返回给定的方法标识符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。

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; } }

allocation_sourcefile(object) → string Show source

返回给定的源文件来源object

有关更多信息和示例,请参阅:trace_object_allocations。

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; } }

allocation_sourceline(object) → string Show source

从给定的返回源的原始行object

有关更多信息和示例,请参阅:trace_object_allocations。

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; } }

count_imemo_objects(result_hash) → hash Show source

Counts objects for each T_IMEMO type.

此方法仅适用于对Ruby程序的性能和内存使用感兴趣的MRI开发人员。

它返回一个散列为:

{:imemo_ifunc=>8, :imemo_svar=>7, :imemo_cref=>509, :imemo_memo=>1, :imemo_throw_data=>1}

如果给出可选参数result_hash,它将被覆盖并返回。这是为了避免探测效应。

返回散列的内容是特定于实现的,将来可能会更改。

在这个版本中,键是符号对象。

这种方法只适用于C Ruby。

static VALUE count_imemo_objects(int argc, VALUE *argv, VALUE self) { VALUE hash = setup_hash(argc, argv if (imemo_type_ids[0] == 0) { imemo_type_ids[0] = rb_intern("imemo_none" imemo_type_ids[1] = rb_intern("imemo_cref" imemo_type_ids[2] = rb_intern("imemo_svar" imemo_type_ids[3] = rb_intern("imemo_throw_data" imemo_type_ids[4] = rb_intern("imemo_ifunc" imemo_type_ids[5] = rb_intern("imemo_memo" imemo_type_ids[6] = rb_intern("imemo_ment" imemo_type_ids[7] = rb_intern("imemo_iseq" } rb_objspace_each_objects(count_imemo_objects_i, (void *)hash return hash; }

count_nodes(result_hash) → hash Show source

计算每个节点类型的节点数。

此方法仅适用于对Ruby程序的性能和内存使用感兴趣的MRI开发人员。

它返回一个散列为:

{:NODE_METHOD=>2027, :NODE_FBODY=>1927, :NODE_CFUNC=>1798, ...}

如果给出可选参数result_hash,它将被覆盖并返回。这是为了避免探测效应。

注意:返回哈希的内容是实现定义的。将来可能会改变。

这种方法只适用于C Ruby。

static VALUE count_nodes(int argc, VALUE *argv, VALUE os) { size_t nodes[NODE_LAST+1]; size_t i; VALUE hash = setup_hash(argc, argv for (i = 0; i <= NODE_LAST; i++) { nodes[i] = 0; } rb_objspace_each_objects(cn_i, &nodes[0] if (hash == Qnil) { hash = rb_hash_new( } else if (!RHASH_EMPTY_P(hash)) { st_foreach(RHASH_TBL(hash), set_zero_i, hash } for (i=0; i<NODE_LAST; i++) { if (nodes[i] != 0) { VALUE node; switch (i) { #define COUNT_NODE(n) case n: node = ID2SYM(rb_intern(#n) break; COUNT_NODE(NODE_SCOPE COUNT_NODE(NODE_BLOCK COUNT_NODE(NODE_IF COUNT_NODE(NODE_CASE COUNT_NODE(NODE_WHEN COUNT_NODE(NODE_OPT_N COUNT_NODE(NODE_WHILE COUNT_NODE(NODE_UNTIL COUNT_NODE(NODE_ITER COUNT_NODE(NODE_FOR COUNT_NODE(NODE_BREAK COUNT_NODE(NODE_NEXT COUNT_NODE(NODE_REDO COUNT_NODE(NODE_RETRY COUNT_NODE(NODE_BEGIN COUNT_NODE(NODE_RESCUE COUNT_NODE(NODE_RESBODY COUNT_NODE(NODE_ENSURE COUNT_NODE(NODE_AND COUNT_NODE(NODE_OR COUNT_NODE(NODE_MASGN COUNT_NODE(NODE_LASGN COUNT_NODE(NODE_DASGN COUNT_NODE(NODE_DASGN_CURR COUNT_NODE(NODE_GASGN COUNT_NODE(NODE_IASGN COUNT_NODE(NODE_IASGN2 COUNT_NODE(NODE_CDECL COUNT_NODE(NODE_CVASGN COUNT_NODE(NODE_CVDECL COUNT_NODE(NODE_OP_ASGN1 COUNT_NODE(NODE_OP_ASGN2 COUNT_NODE(NODE_OP_ASGN_AND COUNT_NODE(NODE_OP_ASGN_OR COUNT_NODE(NODE_OP_CDECL COUNT_NODE(NODE_CALL COUNT_NODE(NODE_FCALL COUNT_NODE(NODE_VCALL COUNT_NODE(NODE_SUPER COUNT_NODE(NODE_ZSUPER COUNT_NODE(NODE_ARRAY COUNT_NODE(NODE_ZARRAY COUNT_NODE(NODE_VALUES COUNT_NODE(NODE_HASH COUNT_NODE(NODE_RETURN COUNT_NODE(NODE_YIELD COUNT_NODE(NODE_LVAR COUNT_NODE(NODE_DVAR COUNT_NODE(NODE_GVAR COUNT_NODE(NODE_IVAR COUNT_NODE(NODE_CONST COUNT_NODE(NODE_CVAR COUNT_NODE(NODE_NTH_REF COUNT_NODE(NODE_BACK_REF COUNT_NODE(NODE_MATCH COUNT_NODE(NODE_MATCH2 COUNT_NODE(NODE_MATCH3 COUNT_NODE(NODE_LIT COUNT_NODE(NODE_STR COUNT_NODE(NODE_DSTR COUNT_NODE(NODE_XSTR COUNT_NODE(NODE_DXSTR COUNT_NODE(NODE_EVSTR COUNT_NODE(NODE_DREGX COUNT_NODE(NODE_DREGX_ONCE COUNT_NODE(NODE_ARGS COUNT_NODE(NODE_ARGS_AUX COUNT_NODE(NODE_OPT_ARG COUNT_NODE(NODE_KW_ARG COUNT_NODE(NODE_POSTARG COUNT_NODE(NODE_ARGSCAT COUNT_NODE(NODE_ARGSPUSH COUNT_NODE(NODE_SPLAT COUNT_NODE(NODE_TO_ARY COUNT_NODE(NODE_BLOCK_ARG COUNT_NODE(NODE_BLOCK_PASS COUNT_NODE(NODE_DEFN COUNT_NODE(NODE_DEFS COUNT_NODE(NODE_ALIAS COUNT_NODE(NODE_VALIAS COUNT_NODE(NODE_UNDEF COUNT_NODE(NODE_CLASS COUNT_NODE(NODE_MODULE COUNT_NODE(NODE_SCLASS COUNT_NODE(NODE_COLON2 COUNT_NODE(NODE_COLON3 COUNT_NODE(NODE_DOT2 COUNT_NODE(NODE_DOT3 COUNT_NODE(NODE_FLIP2 COUNT_NODE(NODE_FLIP3 COUNT_NODE(NODE_SELF COUNT_NODE(NODE_NIL COUNT_NODE(NODE_TRUE COUNT_NODE(NODE_FALSE COUNT_NODE(NODE_ERRINFO COUNT_NODE(NODE_DEFINED COUNT_NODE(NODE_POSTEXE COUNT_NODE(NODE_ALLOCA COUNT_NODE(NODE_BMETHOD COUNT_NODE(NODE_DSYM COUNT_NODE(NODE_ATTRASGN COUNT_NODE(NODE_PRELUDE COUNT_NODE(NODE_LAMBDA #undef COUNT_NODE default: node = INT2FIX(i } rb_hash_aset(hash, node, SIZET2NUM(nodes[i]) } } return hash; }

count_objects(result_hash) → hash Show source

计算按类型分组的所有对象。

它返回一个散列,例如:

{ :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。

static VALUE count_objects(int argc, VALUE *argv, VALUE os) { rb_objspace_t *objspace = &rb_objspace; size_t counts[T_MASK+1]; size_t freed = 0; size_t total = 0; size_t i; VALUE hash; if (rb_scan_args(argc, argv, "01", &hash) == 1) { if (!RB_TYPE_P(hash, T_HASH)) rb_raise(rb_eTypeError, "non-hash given" } for (i = 0; i <= T_MASK; i++) { counts[i] = 0; } for (i = 0; i < heap_allocated_pages; i++) { struct heap_page *page = heap_pages_sorted[i]; RVALUE *p, *pend; p = page->start; pend = p + page->total_slots; for (;p < pend; p++) { if (p->as.basic.flags) { counts[BUILTIN_TYPE(p)]++; } else { freed++; } } total += page->total_slots; } if (hash == Qnil) { hash = rb_hash_new( } else if (!RHASH_EMPTY_P(hash)) { st_foreach(RHASH_TBL_RAW(hash), set_zero, hash } rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total) rb_hash_aset(hash, ID2SYM(rb_intern("FREE")), SIZET2NUM(freed) for (i = 0; i <= T_MASK; i++) { VALUE type; switch (i) { #define COUNT_TYPE(t) case (t): type = ID2SYM(rb_intern(#t) break; COUNT_TYPE(T_NONE COUNT_TYPE(T_OBJECT COUNT_TYPE(T_CLASS COUNT_TYPE(T_MODULE COUNT_TYPE(T_FLOAT COUNT_TYPE(T_STRING COUNT_TYPE(T_REGEXP COUNT_TYPE(T_ARRAY COUNT_TYPE(T_HASH COUNT_TYPE(T_STRUCT COUNT_TYPE(T_BIGNUM COUNT_TYPE(T_FILE COUNT_TYPE(T_DATA COUNT_TYPE(T_MATCH COUNT_TYPE(T_COMPLEX COUNT_TYPE(T_RATIONAL COUNT_TYPE(T_NIL COUNT_TYPE(T_TRUE COUNT_TYPE(T_FALSE COUNT_TYPE(T_SYMBOL COUNT_TYPE(T_FIXNUM COUNT_TYPE(T_IMEMO COUNT_TYPE(T_UNDEF COUNT_TYPE(T_NODE COUNT_TYPE(T_ICLASS COUNT_TYPE(T_ZOMBIE #undef COUNT_TYPE default: type = INT2NUM(i break; } if (counts[i]) rb_hash_aset(hash, type, SIZET2NUM(counts[i]) } return hash; }

count_objects_size(result_hash) → hash Show source

计算每种类型的对象大小(以字节为单位)。

请注意,此信息不完整。您只需要将这些信息作为提示来处理。特别是,T_DATA的总大小可能不正确。

它返回一个散列为:

{:TOTAL=>1461154, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249, ...}

如果给出可选参数result_hash,它将被覆盖并返回。这是为了避免探测效应。

返回的哈希的内容是实现定义的。将来可能会改变。

这种方法只适用于C Ruby。

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; } rb_objspace_each_objects(cos_i, &counts[0] if (hash == Qnil) { hash = rb_hash_new( } else if (!RHASH_EMPTY_P(hash)) { st_foreach(RHASH_TBL(hash), set_zero_i, hash } 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; }

count_symbols(result_hash) → hash Show source

计算每个符号类型的符号。

此方法仅适用于对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)

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( rb_objspace_each_objects(cs_i, &dynamic_counts if (hash == Qnil) { hash = rb_hash_new( } else if (!RHASH_EMPTY_P(hash)) { st_foreach(RHASH_TBL(hash), set_zero_i, hash } 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; }

count_tdata_objects(result_hash) → hash Show source

计算每种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。

static VALUE count_tdata_objects(int argc, VALUE *argv, VALUE self) { VALUE hash = setup_hash(argc, argv rb_objspace_each_objects(cto_i, (void *)hash return hash; }

define_finalizer(obj, aProc=proc()) Show source

添加aProc作为终结器,在obj被销毁后被调用。obj的对象ID 将作为参数传递给aProc。如果aProc是一个lambda或方法,请确保它可以用一个参数调用。

static VALUE define_final(int argc, VALUE *argv, VALUE os) { VALUE obj, block; rb_scan_args(argc, argv, "11", &obj, &block should_be_finalizable(obj if (argc == 1) { block = rb_block_proc( } else { should_be_callable(block } return define_final0(obj, block }

dump(obj, output: :string) # → "{ ... }" Show source

dump(obj,output :: file)#→#<文件:/tmp/rubyobj20131125-88733-1xkfmpv.json>

dump(obj, output: :stdout) # → nil

将一个ruby对象的内容转储为JSON。

这种方法只适用于C Ruby。这是一种实验方法,可能会有所变化。特别是,函数签名和输出格式不能保证在将来版本的ruby中兼容。

static VALUE objspace_dump(int argc, VALUE *argv, VALUE os) { static const char filename[] = "rubyobj"; VALUE obj = Qnil, opts = Qnil, output; struct dump_config dc = {0,}; rb_scan_args(argc, argv, "1:", &obj, &opts output = dump_output(&dc, opts, sym_string, filename dump_object(obj, &dc return dump_result(&dc, output }

dump_all(输出:文件)#→#<文件:/tmp/rubyheap20131125-88469-laoj3v.json>显示源代码

dump_all(output: :stdout) # → nil

dump_all(output: :string) # → "{...}\n{...}\n..."

dump_all(output:

open('heap.json','w')) # → #<File:heap.json>

把ruby堆的内容转储为JSON。

这种方法只适用于C Ruby。这是一种实验方法,可能会有所变化。特别是,函数签名和输出格式不能保证在将来版本的ruby中兼容。

static VALUE objspace_dump_all(int argc, VALUE *argv, VALUE os) { static const char filename[] = "rubyheap"; VALUE opts = Qnil, output; struct dump_config dc = {0,}; rb_scan_args(argc, argv, "0:", &opts output = dump_output(&dc, opts, sym_file, filename /* dump roots */ rb_objspace_reachable_objects_from_root(root_obj_i, &dc if (dc.roots) dump_append(&dc, "]}\n" /* dump all objects */ rb_objspace_each_objects(heap_i, &dc return dump_result(&dc, output }

each_object(module) {|obj| ... } → integer Show source

each_object(module) → an_enumerator

在此Ruby进程中为每个活动的非临时对象调用一次块。如果模块被指定,要求只有那些类或匹配(或者是的子类)的模块的块模块。返回找到的对象数量。直接对象(FixnumS,Symbol小号truefalsenil)都再也没有回来。在下面的例子中,each_object返回我们定义的数字和Math模块中定义的几个常量。

如果没有给出块,则返回一个枚举器。

a = 102.7 b = 95 # Won't be returned c = 12345678987654321 count = ObjectSpace.each_object(Numeric) {|x| p x } puts "Total count: #{count}"

生产:

12345678987654321 102.7 2.71828182845905 3.14159265358979 2.22044604925031e-16 1.7976931348623157e+308 2.2250738585072e-308 Total count: 7

static VALUE os_each_obj(int argc, VALUE *argv, VALUE os) { VALUE of; if (argc == 0) { of = 0; } else { rb_scan_args(argc, argv, "01", &of } RETURN_ENUMERATOR(os, 1, &of return os_obj_of(of }

start → nil Show source

garbage_collect → nil

include GC; garbage_collect → nil

start(full_mark: true, immediate_sweep: true) → nil

garbage_collect(full_mark: true, immediate_sweep: true) → nil

include GC; garbage_collect(full_mark: true, immediate_sweep: true) → nil

启动垃圾回收,除非手动禁用。

该方法使用默认为true的关键字参数进行定义:

def GC.start(full_mark: true, immediate_sweep: true end

使用full_mark:false来执行次要GC。使用immediate_sweep:false推迟清理(使用懒惰扫描)。

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

static VALUE gc_start_internal(int argc, VALUE *argv, VALUE self) { rb_objspace_t *objspace = &rb_objspace; int full_mark = TRUE, immediate_mark = TRUE, immediate_sweep = TRUE; VALUE opt = Qnil; static ID keyword_ids[3]; rb_scan_args(argc, argv, "0:", &opt if (!NIL_P(opt)) { VALUE kwvals[3]; if (!keyword_ids[0]) { keyword_ids[0] = rb_intern("full_mark" keyword_ids[1] = rb_intern("immediate_mark" keyword_ids[2] = rb_intern("immediate_sweep" } rb_get_kwargs(opt, keyword_ids, 0, 3, kwvals if (kwvals[0] != Qundef) full_mark = RTEST(kwvals[0] if (kwvals[1] != Qundef) immediate_mark = RTEST(kwvals[1] if (kwvals[2] != Qundef) immediate_sweep = RTEST(kwvals[2] } garbage_collect(objspace, full_mark, immediate_mark, immediate_sweep, GPR_FLAG_METHOD gc_finalize_deferred(objspace return Qnil; }

internal_class_of(obj) → Class or Module Show source

MRI特定功能

返回obj的内部类。

obj可以是InternalObjectWrapper的一个实例。

请注意,您不应该在您的应用程序中使用此方法。

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 } klass = CLASS_OF(obj return wrap_klass_iow(klass }

internal_super_of(cls) → Class or Module Show source

MRI特定功能

返回cls的内部超类(Class或Module)。

obj可以是InternalObjectWrapper的一个实例。

请注意,您不应该在您的应用程序中使用此方法。

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 = RCLASS_SUPER(obj break; default: rb_raise(rb_eArgError, "class or module is expected" } return wrap_klass_iow(super }

memsize_of(obj) → Integer Show source

返回消耗obj的内存大小。

请注意,退货尺寸不完整。您只需要将这些信息作为提示来处理。尤其是,大小T_DATA可能不正确。

这种方法只适用于C Ruby。

从Ruby 2.2开始,:: memsize_of(obj)返回包含sizeof(RVALUE)的内存大小。

static VALUE memsize_of_m(VALUE self, VALUE obj) { return SIZET2NUM(rb_obj_memsize_of(obj) }

memsize_of_all(klass) → Integer Show source

返回所有活物的内存大小。

如果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。

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 } rb_objspace_each_objects(total_i, &data return SIZET2NUM(data.total }

reachable_objects_from(obj) → array or nil Show source

MRI特定功能

从`obj'返回所有可到达的对象。

这个方法从`obj'返回所有可到达的对象。

如果obj' has two or more references to the same objectx',则返回的数组只包含一个`x'对象。

如果`obj'是一个不可标记(非堆管理)对象,如true,false,nil,symbols和Fixnums(以及Flonum),则它只返回nil。

如果obj' has references to an internal object, then it returns instances of [ObjectSpace::InternalObjectWrapper](objectspace/internalobjectwrapper) class. This object contains a reference to an internal object and you can check the type of internal object with输入'方法。

如果obj' is instance of [ObjectSpace::InternalObjectWrapper](objectspace/internalobjectwrapper) class, then this method returns all reachable object from an internal object, which is pointed byobj'。

用这种方法,你可以发现内存泄漏。

除了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

static VALUE reachable_objects_from(VALUE self, VALUE obj) { if (rb_objspace_markable_object_p(obj)) { VALUE ret = rb_ary_new( struct rof_data data; if (rb_typeddata_is_kind_of(obj, &iow_data_type)) { obj = (VALUE)DATA_PTR(obj } data.refs = st_init_numtable( data.internals = rb_ary_new( rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data st_foreach(data.refs, collect_values, (st_data_t)ret return ret; } else { return Qnil; } }

reachable_objects_from_root → hash Show source

MRI特定功能

从根目录返回所有可到达的对象。

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; }

trace_object_allocations { block } Show source

从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表示法(推荐)。

请注意,此功能会导致巨大的性能下降和巨大的内存消耗。

static VALUE trace_object_allocations(VALUE self) { trace_object_allocations_start(self return rb_ensure(rb_yield, Qnil, trace_object_allocations_stop, self }

trace_object_allocations_clear Show 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; }

trace_object_allocations_debug_start() Show 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 }

trace_object_allocations_start Show 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; }

trace_object_allocations_stop Show source

停止跟踪对象分配。

请注意,如果:: trace_object_allocations_start被调用n次,则在调用:: trace_object_allocations_stop n次后跟踪将停止。

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) { rb_tracepoint_disable(arg->newobj_trace rb_tracepoint_disable(arg->freeobj_trace arg->newobj_trace = 0; arg->freeobj_trace = 0; } return Qnil; }

undefine_finalizer(obj) Show source

删除obj的所有终结器。

static VALUE undefine_final(VALUE os, VALUE obj) { return rb_undefine_finalizer(obj }