123456789_123456789_123456789_123456789_123456789_

Module: ObjectSpace

Relationships & Source Files
Namespace Children
Classes:
Defined in: gc.c,
gc.rb

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

Class Method Summary

Class Method Details

._id2ref(objid) (mod_func)

[ GitHub ]

  
# File 'gc.c', line 3695

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

.count_objects([result_hash]) ⇒ Hash (mod_func)

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.

[ GitHub ]

  
# File 'gc.c', line 4036

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()) (mod_func)

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.

[ GitHub ]

  
# File 'gc.c', line 3246

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([module]) {|obj| ... } ⇒ Integer (mod_func) .each_object([module]) ⇒ Enumerator

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
[ GitHub ]

  
# File 'gc.c', line 3181

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

.garbage_collect(full_mark: true, immediate_mark: true, immediate_sweep: true) (mod_func)

[ GitHub ]

  
# File 'gc.rb', line 164

def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true
  __builtin_gc_start_internal full_mark, immediate_mark, immediate_sweep
end

.undefine_finalizer(obj) (mod_func)

Removes all finalizers for obj.

[ GitHub ]

  
# File 'gc.c', line 3199

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