Module: ObjectSpace

Defined in:
gc.c,
gc.c

Overview

The ObjectSpace module contains a number of routines

that interact with the garbage collection facility and allow you to
traverse all living objects with an iterator.

ObjectSpace also provides support for object finalizers, procs that will be
called when a specific object is about to be destroyed by garbage
collection.

   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}" })

_produces:_

   Finalizer two on 537763470
   Finalizer one on 537763480

Defined Under Namespace

Classes: WeakMap

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

._id2ref(objid) ⇒ Object



3679
3680
3681
3682
3683
# File 'gc.c', line 3679

static VALUE
os_id2ref(VALUE os, VALUE objid)
{
    return id2ref(objid);
}

.count_objects([result_hash]) ⇒ Hash

Counts all objects grouped by type.

It returns a hash, such as:

:TOTAL=>10000,
:FREE=>3011,
:T_OBJECT=>6,
:T_CLASS=>404,
# ...

The contents of the returned hash are implementation specific. It may be changed in future.

The keys starting with :T_ means live objects. For example, :T_ARRAY is the number of arrays. :FREE means object slots which is not used now. :TOTAL means sum of above.

If the optional argument result_hash is given, it is overwritten and returned. This is intended to avoid probe effect.

h = {}
ObjectSpace.count_objects(h)
puts h
# => { :TOTAL=>10000, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249 }

This method is only expected to work on C Ruby.

Returns:



4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
# File 'gc.c', line 4020

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 = Qnil;

    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 (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++) {
            void *poisoned = asan_poisoned_object_p((VALUE)p);
            asan_unpoison_object((VALUE)p, false);
	    if (p->as.basic.flags) {
		counts[BUILTIN_TYPE(p)]++;
	    }
	    else {
		freed++;
	    }
            if (poisoned) {
                GC_ASSERT(BUILTIN_TYPE((VALUE)p) == T_NONE);
                asan_poison_object((VALUE)p);
            }
	}
	total += page->total_slots;
    }

    if (hash == Qnil) {
        hash = rb_hash_new();
    }
    else if (!RHASH_EMPTY_P(hash)) {
        rb_hash_stlike_foreach(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 = type_sym(i);
        if (counts[i])
            rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
    }

    return hash;
}

.define_finalizer(obj, aProc = proc()) ⇒ Object

Adds aProc as a finalizer, to be called after obj was destroyed. The object ID of the obj will be passed as an argument to aProc. If aProc is a lambda or method, make sure it can be called with a single argument.



3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
# File 'gc.c', line 3231

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

.each_object([) {|obj| ... } ⇒ Integer .each_object([) ⇒ Object

Calls the block once for each living, nonimmediate object in this Ruby process. If module is specified, calls the block for only those classes or modules that match (or are a subclass of) module. Returns the number of objects found. Immediate objects (Fixnums, Symbols true, false, and nil) are never returned. In the example below, #each_object returns both the numbers we defined and several constants defined in the Math module.

If no block is given, an enumerator is returned instead.

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

produces:

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

Overloads:

  • .each_object([) {|obj| ... } ⇒ Integer

    Yields:

    • (obj)

    Returns:



3166
3167
3168
3169
3170
3171
3172
3173
3174
# File 'gc.c', line 3166

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

.undefine_finalizer(obj) ⇒ Object

Removes all finalizers for obj.



3184
3185
3186
3187
3188
# File 'gc.c', line 3184

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

Instance Method Details

#_id2ref(objid) ⇒ Object (private)



3679
3680
3681
3682
3683
# File 'gc.c', line 3679

static VALUE
os_id2ref(VALUE os, VALUE objid)
{
    return id2ref(objid);
}

#count_objects([result_hash]) ⇒ Hash (private)

Counts all objects grouped by type.

It returns a hash, such as:

:TOTAL=>10000,
:FREE=>3011,
:T_OBJECT=>6,
:T_CLASS=>404,
# ...

The contents of the returned hash are implementation specific. It may be changed in future.

The keys starting with :T_ means live objects. For example, :T_ARRAY is the number of arrays. :FREE means object slots which is not used now. :TOTAL means sum of above.

If the optional argument result_hash is given, it is overwritten and returned. This is intended to avoid probe effect.

h = {}
ObjectSpace.count_objects(h)
puts h
# => { :TOTAL=>10000, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249 }

This method is only expected to work on C Ruby.

Returns:



4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
# File 'gc.c', line 4020

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 = Qnil;

    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 (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++) {
            void *poisoned = asan_poisoned_object_p((VALUE)p);
            asan_unpoison_object((VALUE)p, false);
	    if (p->as.basic.flags) {
		counts[BUILTIN_TYPE(p)]++;
	    }
	    else {
		freed++;
	    }
            if (poisoned) {
                GC_ASSERT(BUILTIN_TYPE((VALUE)p) == T_NONE);
                asan_poison_object((VALUE)p);
            }
	}
	total += page->total_slots;
    }

    if (hash == Qnil) {
        hash = rb_hash_new();
    }
    else if (!RHASH_EMPTY_P(hash)) {
        rb_hash_stlike_foreach(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 = type_sym(i);
        if (counts[i])
            rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
    }

    return hash;
}

#define_finalizer(obj, aProc = proc()) ⇒ Object (private)

Adds aProc as a finalizer, to be called after obj was destroyed. The object ID of the obj will be passed as an argument to aProc. If aProc is a lambda or method, make sure it can be called with a single argument.



3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
# File 'gc.c', line 3231

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

#each_object([) {|obj| ... } ⇒ Integer (private) #each_object([) ⇒ Object (private)

Calls the block once for each living, nonimmediate object in this Ruby process. If module is specified, calls the block for only those classes or modules that match (or are a subclass of) module. Returns the number of objects found. Immediate objects (Fixnums, Symbols true, false, and nil) are never returned. In the example below, #each_object returns both the numbers we defined and several constants defined in the Math module.

If no block is given, an enumerator is returned instead.

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

produces:

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

Overloads:

  • #each_object([) {|obj| ... } ⇒ Integer

    Yields:

    • (obj)

    Returns:



3166
3167
3168
3169
3170
3171
3172
3173
3174
# File 'gc.c', line 3166

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

#undefine_finalizer(obj) ⇒ Object (private)

Removes all finalizers for obj.



3184
3185
3186
3187
3188
# File 'gc.c', line 3184

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