Spec-Zone.ru › Ruby 2.4

модуль 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 Показать исходный код
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;
}

Преобразует идентификатор объекта в ссылку на объект. Не может быть вызван с идентификатором объекта, переданным в качестве параметра финализатору.

s = "I am a string"                    #=> "I am a string"
r = ObjectSpace._id2ref(s.object_id)   #=> "I am a string"
r == s                                 #=> true
allocation_class_path(object) → string Показать исходный код
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 для получения дополнительной информации и примеров.

allocation_generation(object) → integer or nil Показать исходный код
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 для получения дополнительной информации и примеров.

allocation_method_id(object) → string Показать исходный код
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 для получения дополнительной информации и примеров.

allocation_sourcefile(object) → string Показать исходный код
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 для получения дополнительной информации и примеров.

allocation_sourceline(object) → string Показать исходный код
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 для получения дополнительной информации и примеров.

count_imemo_objects([result_hash]) → hash Показать исходный код
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;
}

Подсчитывает объекты для каждого типа T_IMEMO.

Этот метод предназначен только для разработчиков MRI, заинтересованных в производительности и использовании памяти программами на Ruby.

Возвращает хеш, например:

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

Если необязательный аргумент result_hash задан, он перезаписывается и возвращается. Это предназначено для предотвращения эффекта зондирования.

Содержимое возвращаемого хеша зависит от реализации и может измениться в будущем.

В этой версии ключи — объекты символов.

Ожидается, что этот метод будет работать только с C Ruby.

count_nodes([result_hash]) → hash Показать исходный код
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;
}

Подсчитывает узлы для каждого типа узла.

Этот метод предназначен только для разработчиков MRI, заинтересованных в производительности и использовании памяти программами на Ruby.

Возвращает хеш, например:

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

Если необязательный аргумент result_hash задан, он перезаписывается и возвращается. Это предназначено для предотвращения эффекта зондирования.

Примечание: содержимое возвращаемого хеша определяется реализацией. Оно может быть изменено в будущем.

Этот метод ожидает работу только с C Ruby.

count_objects([result_hash]) → hash Показать исходный код
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;
}

Подсчитывает все объекты, сгруппированные по типу.

Возвращает хеш, например:

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

count_objects_size([result_hash]) → hash Показать исходный код
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;
}

Подсчитывает размер объектов (в байтах) для каждого типа.

Обратите внимание, что эта информация неполная. Вы должны рассматривать её как УКАЗАНИЕ. Особенно, общий размер T_DATA может не соответствовать реальному.

Возвращает хеш, например:

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

Если необязательный аргумент result_hash задан, он перезаписывается и возвращается. Это предназначено для предотвращения эффекта зондирования.

Содержимое возвращаемого хеша зависит от реализации и может измениться в будущем.

Этот метод ожидает работу только с C Ruby.

count_symbols([result_hash]) → hash Показать исходный код
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;
}

Подсчитывает символы для каждого типа символа.

Этот метод предназначен только для разработчиков MRI, заинтересованных в производительности и использовании памяти программами на Ruby.

Если необязательный аргумент result_hash задан, он перезаписывается и возвращается. Это предназначено для предотвращения эффекта зондирования.

Примечание: содержимое возвращаемого хеша определяется реализацией. Оно может быть изменено в будущем.

В этой версии 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)
count_tdata_objects([result_hash]) → hash Показать исходный код
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;
}

Подсчитывает объекты для каждого типа T_DATA.

Этот метод предназначен только для разработчиков MRI, заинтересованных в производительности и использовании памяти программами на Ruby.

Возвращает хеш, например:

{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 задан, он перезаписывается и возвращается. Это предназначено для предотвращения эффекта зондирования.

Содержимое возвращаемого хеша зависит от реализации и может измениться в будущем.

В этой версии ключи — объект класса или объект символа.

Если объект является обычным (доступным) объектом, ключ — объект класса. Если объект не является обычным (внутренним) объектом, ключ — имя символа, зарегистрированного в rb_data_type_struct.

Этот метод ожидает работу только с C Ruby.

define_finalizer(obj, aProc=proc()) Показать исходный код
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);
}

Добавляет aProc в качестве финализатора, который вызывается после уничтожения obj. Идентификатор объекта obj будет передан в качестве аргумента aProc. Если aProc является лямбдой или методом, убедитесь, что он может быть вызван с одним аргументом.

dump(obj[, output: :string]) # → "{ ... }" Показать исходный код
dump(obj, output: :file) # → #<File:/tmp/rubyobj20131125-88733-1xkfmpv.json>
dump(obj, output: :stdout) # → nil
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);
}

Выводит содержимое объекта Ruby в формате JSON.

Этот метод предназначен только для работы с C Ruby. Это экспериментальный метод и может быть изменён. В частности, сигнатура функции и формат вывода не гарантируют совместимость с будущими версиями Ruby.

dump_all([output: :file]) # → #<File:/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>
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);
}

Выводит содержимое кучи Ruby в формате JSON.

Этот метод предназначен только для работы с C Ruby. Это экспериментальный метод и может быть изменён. В частности, сигнатура функции и формат вывода не гарантируются как совместимые в будущих версиях Ruby.

each_object([module]) {|obj| ... } → integer Показать исходный код
each_object([module]) → an_enumerator
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);
}

Вызывает блок для каждого активного, не-немедленного объекта в этом процессе Ruby. Если задан module, вызывает блок только для тех классов или модулей, которые соответствуют (или являются подклассом) module. Возвращает количество найденных объектов. Немедленные объекты (Fixnums, Symbols true, false, и nils) никогда не возвращаются. В примере ниже, 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
start → nil Показать исходный код
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
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;
}

Инициализирует сборку мусора, если она не отключена вручную.

Этот метод определён с ключевыми аргументами, которые по умолчанию равны true:

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

Используйте full_mark: false для выполнения малой GC. Используйте immediate_sweep: false для отложенного сканирования (используйте ленивое сканирование).

Примечание: Эти ключевые аргументы зависят от реализации и версии. Они не гарантируют совместимость в будущем и могут быть проигнорированы, если реализация их не поддерживает.

internal_class_of(obj) → Class or Module Показать исходный код
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);
}
Специфичная для MRI функция

Возвращает внутренний класс объекта obj.

obj может быть экземпляром InternalObjectWrapper.

Обратите внимание, что вы не должны использовать этот метод в своём приложении.

internal_super_of(cls) → Class or Module Показать исходный код
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);
}
Специфичная для MRI функция

Возвращает внутренний суперкласс cls (Класс или Модуль).

obj может быть экземпляром InternalObjectWrapper.

Обратите внимание, что вы не должны использовать этот метод в своём приложении.

memsize_of(obj) → Integer Показать исходный код
static VALUE
memsize_of_m(VALUE self, VALUE obj)
{
    return SIZET2NUM(rb_obj_memsize_of(obj));
}

Возвращает занимаемый объём памяти объектом obj.

Обратите внимание, что возвращаемый размер неполный. Вам нужно обрабатывать эту информацию только как УКАЗАНИЕ. В частности, размер T_DATA может быть неверным.

Этот метод предназначен только для работы с C Ruby.

Начиная с Ruby 2.2, ::memsize_of(obj) возвращает размер памяти, включая sizeof(RVALUE).

memsize_of_all([klass]) → Integer Показать исходный код
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);
}

Возвращает общий объём памяти, занимаемый всеми активными объектами.

Если задан 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.

reachable_objects_from(obj) → array or nil Показать исходный код
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;
    }
}
Специфичная для MRI функция

Возвращает все достижимые объекты от `obj'.

Этот метод возвращает все достижимые объекты от `obj'.

Если `obj' имеет два или более ссылок на тот же объект `x', то возвращаемый массив содержит только один объект `x'.

Если `obj' является недостижимым (неуправляемым объектом кучи), таким как true, false, nil, символы и 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
reachable_objects_from_root → hash Показать исходный код
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 функция

Возвращает все достижимые объекты от корневых.

trace_object_allocations { block } Показать исходный код
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 (рекомендуется).

Обратите внимание, что эта функция приводит к значительному снижению производительности и большому потреблению памяти.

trace_object_allocations_clear Показать исходный код
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() Показать исходный код
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 Показать исходный код
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 Показать исходный код
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;
}

Останавливает отслеживание выделения объектов.

Обратите внимание, что если ::trace_object_allocations_start вызывается n раз, то отслеживание остановится после вызова ::trace_object_allocations_stop n раз.

undefine_finalizer(obj) Показать исходный код
static VALUE
undefine_final(VALUE os, VALUE obj)
{
    return rb_undefine_finalizer(obj);
}

Удаляет все финализаторы для obj.

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API