модуль 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
Публичные методы класса
Исходный код
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 для получения дополнительной информации и примеров.
Исходный код
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 для получения дополнительной информации и примеров.
Исходный код
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 для получения дополнительной информации и примеров.
Исходный код
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 для получения дополнительной информации и примеров.
Исходный код
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 для получения дополнительной информации и примеров.
Исходный код
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.
Исходный код
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.
Исходный код
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.
Исходный код
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.
Исходный код
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)
Исходный код
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.
Исходный код
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
Также обратите внимание, что финализация может быть непредсказуемой и никогда не гарантируется, что она будет выполнена, кроме как при выходе.
Исходный код
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
Исходный код
# 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
Исходный код
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.
Обратите внимание, что вы не должны использовать этот метод в своём приложении.
Исходный код
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);
} obj может быть экземпляром InternalObjectWrapper.
Обратите внимание, что вы не должны использовать этот метод в своём приложении.
Исходный код
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).
Исходный код
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.
Исходный код
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
Исходный код
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
-
Возвращает все достижимые объекты от корня.
Исходный код
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 (рекомендуется).
Обратите внимание, что эта функция приводит к значительному снижению производительности и увеличению потребления памяти.
Исходный код
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;
} Очищает записанную информацию об отслеживании.
Исходный код
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);
} Исходный код
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;
} Начинает отслеживание выделения объектов.
Исходный код
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 раз.
Исходный код
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.
Публичные методы экземпляров
Исходный код
# 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.
Исходный код
# 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.
Исходный код
# 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.
Приватные методы экземпляров
Исходный код
# 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.