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进程中为每个活动的非临时对象调用一次块。如果模块被指定,要求只有那些类或匹配(或者是的子类)的模块的块模块。返回找到的对象数量。直接对象(Fixnum
S,Symbol
小号true
,false
和nil
)都再也没有回来。在下面的例子中,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 object
x',则返回的数组只包含一个`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 by
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
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);
}
本文档系腾讯云开发者社区成员共同维护,如有问题请联系 cloudcommunity@tencent.com