Spec-Zone.ru › Ruby 3.4

модуль ObjectSpace

Библиотека objspace расширяет модуль ObjectSpace и добавляет несколько методов для получения внутренней статистической информации об управлении объектами/памятью.

Вам необходимо require 'objspace' для использования этого расширенного модуля.

В целом, вы НЕ ДОЛЖНЫ использовать эту библиотеку, если не знаете о реализации MRI. В основном, эта библиотека предназначена для разработчиков профилировщиков памяти и разработчиков MRI, которым необходимо узнать об использовании памяти MRI.

Модуль ObjectSpace содержит ряд процедур, которые взаимодействуют с механизмом сбора мусора и позволяют перебирать все живые объекты с помощью итератора.

ObjectSpace также предоставляет поддержку для финализаторов объектов, процедур, которые будут вызваны после того, как конкретный объект был уничтожен сборщиком мусора. Обратитесь к документации для ObjectSpace.define_finalizer для важной информации о правильном использовании этого метода.

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

a = nil
b = nil

производит:

Finalizer two on 537763470
Finalizer one on 537763480

Публичные методы класса

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) → integer
Исходный код
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) {
#define INIT_IMEMO_TYPE_ID(n) (imemo_type_ids[n] = rb_intern_const(#n))
        INIT_IMEMO_TYPE_ID(imemo_env);
        INIT_IMEMO_TYPE_ID(imemo_cref);
        INIT_IMEMO_TYPE_ID(imemo_svar);
        INIT_IMEMO_TYPE_ID(imemo_throw_data);
        INIT_IMEMO_TYPE_ID(imemo_ifunc);
        INIT_IMEMO_TYPE_ID(imemo_memo);
        INIT_IMEMO_TYPE_ID(imemo_ment);
        INIT_IMEMO_TYPE_ID(imemo_iseq);
        INIT_IMEMO_TYPE_ID(imemo_tmpbuf);
        INIT_IMEMO_TYPE_ID(imemo_ast);
        INIT_IMEMO_TYPE_ID(imemo_parser_strterm);
        INIT_IMEMO_TYPE_ID(imemo_callinfo);
        INIT_IMEMO_TYPE_ID(imemo_callcache);
        INIT_IMEMO_TYPE_ID(imemo_constcache);
#undef INIT_IMEMO_TYPE_ID
    }

    each_object_with_flags(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)
{
    return setup_hash(argc, argv);
}

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

Этот метод предназначен только для разработчиков 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)
{
    struct count_objects_data data = { 0 };
    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");
    }

    rb_gc_impl_each_object(rb_gc_get_objspace(), count_objects_i, &data);

    if (NIL_P(hash)) {
        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(data.total));
    rb_hash_aset(hash, ID2SYM(rb_intern("FREE")), SIZET2NUM(data.freed));

    for (size_t i = 0; i <= T_MASK; i++) {
        VALUE type = type_sym(i);
        if (data.counts[i])
            rb_hash_aset(hash, type, SIZET2NUM(data.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;
    }

    each_object_with_flags(cos_i, &counts[0]);

    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();
    each_object_with_flags(cs_i, &dynamic_counts);

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

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

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

Если указан необязательный аргумент 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)
count_tdata_objects([result_hash]) → hash
Исходный код
static VALUE
count_tdata_objects(int argc, VALUE *argv, VALUE self)
{
    VALUE hash = setup_hash(argc, argv);
    each_object_with_flags(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, он перезаписывается и возвращается. Это сделано для того, чтобы избежать эффекта зондирования.

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

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

Если объект является обычным (доступным) объектом, ключом является объект Class. Если объект не является обычным (внутренним) объектом, ключом является имя символа, зарегистрированное с помощью 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);
    if (argc == 1) {
        block = rb_block_proc();
    }

    if (rb_callable_receiver(block) == obj) {
        rb_warn("finalizer references object to be finalized");
    }

    return rb_define_finalizer(obj, block);
}

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

Возвращаемое значение — массив [0, aProc].

Два рекомендуемых подхода: создать процедуру-финализатор в методе, не связанном с экземпляром, где она может безопасно захватить необходимые данные, или использовать пользовательский вызываемый объект, который явно хранит необходимые данные в качестве переменных экземпляра.

class Foo
  def initialize(data_needed_for_finalization)
    ObjectSpace.define_finalizer(self, self.class.create_finalizer(data_needed_for_finalization))
  end

  def self.create_finalizer(data_needed_for_finalization)
    proc {
      puts "finalizing #{data_needed_for_finalization}"
    }
  end
end

class Bar
 class Remover
    def initialize(data_needed_for_finalization)
      @data_needed_for_finalization = data_needed_for_finalization
    end

    def call(id)
      puts "finalizing #{@data_needed_for_finalization}"
    end
  end

  def initialize(data_needed_for_finalization)
    ObjectSpace.define_finalizer(self, Remover.new(data_needed_for_finalization))
  end
end

Обратите внимание, что если ваш финализатор ссылается на объект, подлежащий финализации, он никогда не будет запущен во время GC, хотя он по-прежнему будет запущен при выходе. Вы получите предупреждение, если вы захватите объект, подлежащий финализации, в качестве получателя финализатора.

class CapturesSelf
  def initialize(name)
    ObjectSpace.define_finalizer(self, proc {
      # this finalizer will only be run on exit
      puts "finalizing #{name}"
    })
  end
end

Также обратите внимание, что финализация может быть непредсказуемой и никогда не гарантируется, что она будет выполнена, кроме как при выходе.

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

Вызывает блок один раз для каждого существующего, не мгновенного объекта в этом процессе 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
garbage_collect (full_mark: true, immediate_mark: true, immediate_sweep: true)
Исходный код
# File gc.rb, line 395
def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true
  Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false
end

Псевдоним для GC.start

internal_class_of(obj) → Класс или Модуль
Исходный код
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);
    }

    if (RB_TYPE_P(obj, T_IMEMO)) {
        return Qnil;
    }
    else {
        klass = CLASS_OF(obj);
        return wrap_klass_iow(klass);
    }
}
Функция, специфичная для MRI

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

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

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

internal_super_of(cls) → Класс или Модуль
Исходный код
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 (Class или Module).

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

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

memsize_of(obj) → Целое число
Исходный код
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]) → Целое число
Исходный код
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);
    }

    each_object_with_flags(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) → массив или nil
Исходный код
static VALUE
reachable_objects_from(VALUE self, VALUE obj)
{
    if (!RB_SPECIAL_CONST_P(obj)) {
        struct rof_data data;

        if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
            obj = (VALUE)DATA_PTR(obj);
        }

        data.refs = rb_obj_hide(rb_ident_hash_new());
        data.values = rb_ary_new();

        rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data);

        return data.values;
    }
    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 → словарь
Исходный код
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 { блок }
Исходный код
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) {
        if (arg->newobj_trace != 0) {
            rb_tracepoint_disable(arg->newobj_trace);
        }
        if (arg->freeobj_trace != 0) {
            rb_tracepoint_disable(arg->freeobj_trace);
        }
    }

    return Qnil;
}

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

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

undefine_finalizer(obj)
Исходный код
static VALUE
undefine_final(VALUE os, VALUE obj)
{
    rb_check_frozen(obj);

    rb_gc_impl_undefine_finalizer(rb_gc_get_objspace(), obj);

    return obj;
}

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

Публичные методы экземпляров

dump (obj, output: :string)
Исходный код
# File ext/objspace/lib/objspace.rb, line 28
def dump(obj, output: :string)
  out = case output
  when :file, nil
    require 'tempfile'
    Tempfile.create(%w(rubyobj .json))
  when :stdout
    STDOUT
  when :string
    +''
  when IO
    output
  else
    raise ArgumentError, "wrong output option: #{output.inspect}"
  end

  ret = _dump(obj, out)
  return nil if output == :stdout
  ret
end

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

output может быть одним из: :stdout, :file, :string, или объектом IO.

  • :file означает вывод в временный файл и возврат соответствующего объекта File;

  • :stdout означает вывод в консоль и возврат nil;

  • :string означает возврат строки с выводом;

  • если предоставлен объект типа IO, вывод будет направлен туда, и объект будет возвращён.

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

dump_all (output: :file, full: false, since: nil, shapes: true)
Исходный код
# File ext/objspace/lib/objspace.rb, line 84
def dump_all(output: :file, full: false, since: nil, shapes: true)
  out = case output
  when :file, nil
    require 'tempfile'
    Tempfile.create(%w(rubyheap .json))
  when :stdout
    STDOUT
  when :string
    +''
  when IO
    output
  else
    raise ArgumentError, "wrong output option: #{output.inspect}"
  end

  shapes = 0 if shapes == true
  ret = _dump_all(out, full, since, shapes)
  return nil if output == :stdout
  ret
end

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

Аргумент output такой же, как и для dump.

full должно быть булевым значением. Если true, то будут выведены все слоты кучи, включая пустые (T_NONE).

since должно быть неотрицательным целым числом или nil.

Если since — положительное целое число, то выводится только объекты этой и более поздних поколений. Текущее поколение можно получить используя GC::count. Объекты, выделенные без включённого отслеживания выделения объектов, игнорируются. Для получения дополнительной информации и примеров см. ::trace_object_allocations.

Если since опущено или равно nil, то будут выведены все объекты.

shapes должно быть булевым значением или неотрицательным целым числом.

Если shapes — положительное целое число, то будут выведены только формы, более новые, чем указанный идентификатор формы. Текущий идентификатор формы можно получить используя RubyVM.stat(:next_shape_id).

Если shapes равно false, то формы не выводятся.

Для вывода только объектов, выделенных после определённого момента, можно комбинировать since и shapes:

ObjectSpace.trace_object_allocations
GC.start
gc_generation = GC.count
shape_generation = RubyVM.stat(:next_shape_id)
call_method_to_instrument
ObjectSpace.dump_all(since: gc_generation, shapes: shape_generation)

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

dump_shapes (output: :file, since: 0)
Исходный код
# File ext/objspace/lib/objspace.rb, line 116
def dump_shapes(output: :file, since: 0)
  out = case output
  when :file, nil
    require 'tempfile'
    Tempfile.create(%w(rubyshapes .json))
  when :stdout
    STDOUT
  when :string
    +''
  when IO
    output
  else
    raise ArgumentError, "wrong output option: #{output.inspect}"
  end

  ret = _dump_shapes(out, since)
  return nil if output == :stdout
  ret
end

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

Аргумент output такой же, как и для dump.

Если since — положительное целое число, то выводится только формы, более новые, чем указанный идентификатор формы. Текущий идентификатор формы можно получить используя RubyVM.stat(:next_shape_id).

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

Приватные методы экземпляров

garbage_collect (full_mark: true, immediate_mark: true, immediate_sweep: true)
Исходный код
# File gc.rb, line 395
def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true
  Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false
end

Псевдоним для GC.start

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

Spec-Zone.ru

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