module ObjectSpace
Die Bibliothek objspace erweitert das Modul ObjectSpace und fügt mehrere Methoden hinzu, um interne statistische Informationen über die Objekt-/Speicherverwaltung zu erhalten.
Sie müssen require 'objspace' verwenden, um dieses Erweiterungsmodul zu nutzen.
Im Allgemeinen SOLLTEN Sie diese Bibliothek **NICHT** verwenden, wenn Sie die MRI-Implementierung nicht kennen. Hauptsächlich ist diese Bibliothek für (Speicher-)Profiler-Entwickler und MRI-Entwickler gedacht, die die MRI-Speichernutzung kennen müssen.
Das Modul ObjectSpace enthält eine Reihe von Routinen, die mit der Garbage-Collection-Einrichtung interagieren und es Ihnen ermöglichen, alle lebenden Objekte mit einem Iterator zu durchlaufen.
ObjectSpace bietet auch Unterstützung für Objektfinalisierer, das sind Procs, die aufgerufen werden, nachdem ein bestimmtes Objekt durch die Garbage-Collection zerstört wurde. Siehe die Dokumentation für ObjectSpace.define_finalizer für wichtige Informationen zur korrekten Verwendung dieser Methode.
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
ergibt
Finalizer two on 537763470 Finalizer one on 537763480
Öffentliche Klassenmethoden
Source
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;
}
}
Gibt die Klasse für das gegebene object zurück.
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"
Siehe ::trace_object_allocations für weitere Informationen und Beispiele.
Source
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;
}
}
Gibt die Garbage-Collector-Generation für das gegebene object zurück.
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"
Siehe ::trace_object_allocations für weitere Informationen und Beispiele.
Source
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;
}
}
Gibt die Methoden-ID für das gegebene object zurück.
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"
Siehe ::trace_object_allocations für weitere Informationen und Beispiele.
Source
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;
}
}
Gibt die Quelldatei-Herkunft des gegebenen object zurück.
Siehe ::trace_object_allocations für weitere Informationen und Beispiele.
Source
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;
}
}
Gibt die ursprüngliche Zeile aus der Quelle für das gegebene object zurück.
Siehe ::trace_object_allocations für weitere Informationen und Beispiele.
Source
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_callinfo);
INIT_IMEMO_TYPE_ID(imemo_callcache);
INIT_IMEMO_TYPE_ID(imemo_constcache);
INIT_IMEMO_TYPE_ID(imemo_fields);
#undef INIT_IMEMO_TYPE_ID
}
each_object_with_flags(count_imemo_objects_i, (void *)hash);
return hash;
}
Zählt Objekte für jeden T_IMEMO-Typ.
Diese Methode ist nur für MRI-Entwickler gedacht, die an der Leistung und Speichernutzung von Ruby-Programmen interessiert sind.
Sie gibt einen Hash zurück wie
{:imemo_ifunc=>8,
:imemo_svar=>7,
:imemo_cref=>509,
:imemo_memo=>1,
:imemo_throw_data=>1}
Wenn das optionale Argument result_hash angegeben wird, wird es überschrieben und zurückgegeben. Dies soll den Probeneffekt vermeiden.
Der Inhalt des zurückgegebenen Hash ist implementierungsspezifisch und kann sich in Zukunft ändern.
In dieser Version sind die Schlüssel Symbolobjekte.
Diese Methode ist voraussichtlich nur auf C Ruby lauffähig.
Source
static VALUE
count_nodes(int argc, VALUE *argv, VALUE os)
{
return setup_hash(argc, argv);
}
Zählt Knoten für jeden Knotentyp.
Diese Methode ist nur für MRI-Entwickler gedacht, die an der Leistung und Speichernutzung von Ruby-Programmen interessiert sind.
Sie gibt einen Hash zurück wie
{:NODE_METHOD=>2027, :NODE_FBODY=>1927, :NODE_CFUNC=>1798, ...}
Wenn das optionale Argument result_hash angegeben wird, wird es überschrieben und zurückgegeben. Dies soll den Probeneffekt vermeiden.
Hinweis: Der Inhalt des zurückgegebenen Hash ist implementierungsabhängig. Er kann sich in Zukunft ändern.
Diese Methode ist voraussichtlich nur auf C Ruby lauffähig.
Source
static VALUE
count_objects(int argc, VALUE *argv, VALUE os)
{
struct count_objects_data data = { 0 };
VALUE hash = Qnil;
VALUE types[T_MASK + 1];
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 (size_t i = 0; i <= T_MASK; i++) {
// type_sym can allocate an object,
// so we need to create all key symbols in advance
// not to disturb the result
types[i] = type_sym(i);
}
// Same as type_sym, we need to create all key symbols in advance
VALUE total = ID2SYM(rb_intern("TOTAL"));
VALUE free = ID2SYM(rb_intern("FREE"));
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, total, SIZET2NUM(data.total));
rb_hash_aset(hash, free, SIZET2NUM(data.freed));
for (size_t i = 0; i <= T_MASK; i++) {
if (data.counts[i]) {
rb_hash_aset(hash, types[i], SIZET2NUM(data.counts[i]));
}
}
return hash;
}
Zählt alle Objekte gruppiert nach Typ.
Sie gibt einen Hash zurück, wie z.B.
{
:TOTAL=>10000,
:FREE=>3011,
:T_OBJECT=>6,
:T_CLASS=>404,
# ...
}
Der Inhalt des zurückgegebenen Hash ist implementierungsspezifisch. Er kann sich in Zukunft ändern.
Die Schlüssel, die mit :T_ beginnen, bedeuten lebende Objekte. Zum Beispiel ist :T_ARRAY die Anzahl der Arrays. :FREE bedeutet Objekt-Slots, die jetzt nicht verwendet werden. :TOTAL bedeutet die Summe der oben genannten.
Wenn das optionale Argument result_hash angegeben wird, wird es überschrieben und zurückgegeben. Dies soll den Probeneffekt vermeiden.
h = {} ObjectSpace.count_objects(h) puts h # => { :TOTAL=>10000, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249 }
Diese Methode ist voraussichtlich nur auf C Ruby lauffähig.
Source
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;
}
Zählt die Objektgrößen (in Bytes) für jeden Typ.
Beachten Sie, dass diese Informationen unvollständig sind. Sie müssen diese Informationen nur als HINWEIS behandeln. Insbesondere die Gesamtgröße von T_DATA kann falsch sein.
Sie gibt einen Hash zurück wie
{:TOTAL=>1461154, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249, ...}
Wenn das optionale Argument result_hash angegeben wird, wird es überschrieben und zurückgegeben. Dies soll den Probeneffekt vermeiden.
Der Inhalt des zurückgegebenen Hash ist implementierungsabhängig. Er kann sich in Zukunft ändern.
Diese Methode ist voraussichtlich nur auf C Ruby lauffähig.
Source
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;
}
Zählt Symbole für jeden Symbol-Typ.
Diese Methode ist nur für MRI-Entwickler gedacht, die an der Leistung und Speichernutzung von Ruby-Programmen interessiert sind.
Wenn das optionale Argument result_hash angegeben wird, wird es überschrieben und zurückgegeben. Dies soll den Probeneffekt vermeiden.
Hinweis: Der Inhalt des zurückgegebenen Hash ist implementierungsabhängig. Er kann sich in Zukunft ändern.
Diese Methode ist voraussichtlich nur auf C Ruby lauffähig.
Auf dieser Version von MRI gibt es 3 Arten von Symbolen (und 1 Gesamtzählung).
* 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)
Source
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;
}
Zählt Objekte für jeden T_DATA-Typ.
Diese Methode ist nur für MRI-Entwickler gedacht, die an der Leistung und Speichernutzung von Ruby-Programmen interessiert sind.
Sie gibt einen Hash zurück wie
{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.
Wenn das optionale Argument result_hash angegeben wird, wird es überschrieben und zurückgegeben. Dies soll den Probeneffekt vermeiden.
Der Inhalt des zurückgegebenen Hash ist implementierungsspezifisch und kann sich in Zukunft ändern.
In dieser Version sind die Schlüssel ein Klassenobjekt oder ein Symbol-Objekt.
Wenn das Objekt eine Art von normalem (zugänglichem) Objekt ist, ist der Schlüssel das Klassenobjekt. Wenn das Objekt keine Art von normalem (internem) Objekt ist, ist der Schlüssel der Symbolname, der von rb_data_type_struct registriert wurde.
Diese Methode ist voraussichtlich nur auf C Ruby lauffähig.
Source
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);
}
Fügt aProc als Finalisierer hinzu, der aufgerufen wird, nachdem obj zerstört wurde. Die Objekt-ID von obj wird als Argument an aProc übergeben. Wenn aProc ein Lambda oder eine Methode ist, stellen Sie sicher, dass sie mit einem einzigen Argument aufgerufen werden kann.
Der Rückgabewert ist ein Array [0, aProc].
Die beiden empfohlenen Muster sind entweder, den Finalisierer-Proc in einer Nicht-Instanzmethode zu erstellen, wo er sicher den benötigten Zustand erfassen kann, oder ein benutzerdefiniertes aufrufbares Objekt zu verwenden, das den benötigten Zustand explizit als Instanzvariablen speichert.
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
Beachten Sie, dass wenn Ihr Finalisierer auf das zu finalisierende Objekt verweist, es niemals bei GC ausgeführt wird, obwohl es beim Beenden immer noch ausgeführt wird. Sie erhalten eine Warnung, wenn Sie das zu finalisierende Objekt als Empfänger des Finalisierers erfassen.
class CapturesSelf def initialize(name) ObjectSpace.define_finalizer(self, proc { # this finalizer will only be run on exit puts "finalizing #{name}" }) end end
Beachten Sie auch, dass die Finalisierung unvorhersehbar sein kann und nie garantiert wird, außer beim Beenden.
Source
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);
}
Ruft den Block einmal für jedes lebende, nicht-sofortige Objekt in diesem Ruby-Prozess auf. Wenn module angegeben ist, ruft es den Block nur für die Klassen oder Module auf, die mit module übereinstimmen (oder Unterklassen davon sind). Gibt die Anzahl der gefundenen Objekte zurück. Sofortige Objekte (wie Fixnums, statische Symbols true, false und nil) werden niemals zurückgegeben.
Wenn kein Block angegeben wird, wird stattdessen ein Enumerator zurückgegeben.
Job = Class.new jobs = [Job.new, Job.new] count = ObjectSpace.each_object(Job) {|x| p x } puts "Total count: #{count}"
ergibt
#<Job:0x000000011d6cbbf0> #<Job:0x000000011d6cbc68> Total count: 2
Aufgrund eines aktuellen Ractor-Implementierungsproblems liefert diese Methode keine Ractor-nicht teilbaren Objekte, wenn der Prozess im Multi-Ractor-Modus läuft. Der Multi-Ractor-Modus wird aktiviert, wenn Ractor.new zum ersten Mal aufgerufen wurde. Siehe bugs.ruby-lang.org/issues/19387 für weitere Informationen.
a = 12345678987654321 # shareable b = [].freeze # shareable c = {} # not shareable ObjectSpace.each_object {|x| x } # yields a, b, and c Ractor.new {} # enter multi-Ractor mode ObjectSpace.each_object {|x| x } # does not yield c
Source
# File gc.rb, line 594 def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false end
Alias von GC.start
Source
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-spezifisches Feature
-
Gibt die interne Klasse von obj zurück.
obj kann eine Instanz von InternalObjectWrapper sein.
Beachten Sie, dass Sie diese Methode nicht in Ihrer Anwendung verwenden sollten.
Source
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 = rb_class_super_of(obj);
break;
default:
rb_raise(rb_eArgError, "class or module is expected");
}
return wrap_klass_iow(super);
}
- MRI-spezifisches Feature
-
Gibt die interne Superklasse von cls (Class oder Module) zurück.
obj kann eine Instanz von InternalObjectWrapper sein.
Beachten Sie, dass Sie diese Methode nicht in Ihrer Anwendung verwenden sollten.
Source
static VALUE
memsize_of_m(VALUE self, VALUE obj)
{
return SIZET2NUM(rb_obj_memsize_of(obj));
}
Gibt die verbrauchte Speichergröße von obj in Bytes zurück.
Beachten Sie, dass die zurückgegebene Größe unvollständig ist. Sie müssen diese Informationen nur als HINWEIS behandeln. Insbesondere die Größe von T_DATA ist möglicherweise nicht korrekt.
Diese Methode ist voraussichtlich nur auf CRuby lauffähig.
Ab Ruby 3.2 mit Variable Width Allocation gibt sie die tatsächlich genutzte Slot-Größe plus zusätzlichen außerhalb des Slots allozierten Speicher (wie externe Strings, Arrays oder Hash-Tabellen) zurück.
Source
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);
}
Gibt die verbrauchte Speichergröße aller lebenden Objekte in Bytes zurück.
Wenn klass (sollte ein Klassenobjekt sein) angegeben ist, gibt sie die gesamte Speichergröße von Instanzen der gegebenen Klasse zurück.
Beachten Sie, dass die zurückgegebene Größe unvollständig ist. Sie müssen diese Informationen nur als HINWEIS behandeln. Insbesondere die Größe von T_DATA ist möglicherweise nicht korrekt.
Beachten Sie, dass diese Methode **NICHT** die gesamte malloc’te Speichergröße zurückgibt.
Diese Methode kann durch den folgenden Ruby-Code definiert werden
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
Diese Methode ist voraussichtlich nur auf C Ruby lauffähig.
Source
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-spezifisches Feature
-
Gibt alle von 'obj' erreichbaren Objekte zurück.
Diese Methode gibt alle von 'obj' erreichbaren Objekte zurück.
Wenn 'obj' zwei oder mehr Referenzen auf dasselbe Objekt 'x' hat, dann enthält das zurückgegebene Array nur ein 'x'-Objekt.
Wenn 'obj' ein nicht markierbares (nicht heap-verwaltetes) Objekt wie true, false, nil, Symbole und Fixnums (und Flonums) ist, gibt es einfach nil zurück.
Wenn 'obj' Referenzen auf ein internes Objekt hat, gibt es Instanzen der Klasse ObjectSpace::InternalObjectWrapper zurück. Dieses Objekt enthält eine Referenz auf ein internes Objekt und Sie können den Typ des internen Objekts mit der Methode 'type' überprüfen.
Wenn 'obj' eine Instanz der Klasse ObjectSpace::InternalObjectWrapper ist, gibt diese Methode alle von einem internen Objekt erreichbaren Objekte zurück, auf das von 'obj' verwiesen wird.
Mit dieser Methode können Sie Speicherlecks finden.
Diese Methode ist voraussichtlich nur auf C Ruby lauffähig.
Beispiel
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
Source
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-spezifisches Feature
-
Gibt alle vom Root erreichbaren Objekte zurück.
Source
static VALUE
trace_object_allocations(VALUE self)
{
trace_object_allocations_start(self);
return rb_ensure(rb_yield, Qnil, trace_object_allocations_stop, self);
}
Beginnt die Verfolgung von Objektzuweisungen aus dem Erweiterungsmodul ObjectSpace.
Zum Beispiel
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"
Dieses Beispiel hat das Modul ObjectSpace einbezogen, um die Lesbarkeit zu verbessern, aber Sie können auch die Notation ::trace_object_allocations verwenden (empfohlen).
Beachten Sie, dass diese Funktion eine enorme Leistungsabnahme und einen enormen Speicherverbrauch verursacht.
Source
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;
}
Löscht aufgezeichnete Verfolgungsinformationen.
Source
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);
}
Beginnt die Verfolgung von Objektzuweisungen für die GC-Fehlersuche. Wenn Sie auf den BUG „… ist T_NONE“ (und so weiter) in Ihrer Anwendung stoßen, versuchen Sie diese Methode am Anfang Ihrer App.
Source
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;
}
Beginnt die Verfolgung von Objektzuweisungen.
Source
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;
}
Stoppt die Verfolgung von Objektzuweisungen.
Beachten Sie, dass, wenn ::trace_object_allocations_start n-mal aufgerufen wird, die Verfolgung nach n-maligem Aufruf von ::trace_object_allocations_stop stoppt.
Source
static VALUE
undefine_final(VALUE os, VALUE obj)
{
return rb_undefine_finalizer(obj);
}
Entfernt alle Finalisierer für obj.
Öffentliche Instanzmethoden
Source
# 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
Gibt den Inhalt eines Ruby-Objekts als JSON aus.
output kann sein: :stdout, :file, :string oder ein IO-Objekt.
-
:filebedeutet die Ausgabe in eine temporäre Datei und die Rückgabe des entsprechendenFile-Objekts; -
:stdoutbedeutet die Ausgabe des Dumps und die Rückgabe vonnil; -
:stringbedeutet die Rückgabe eines Strings mit dem Dump; -
wenn eine Instanz eines
IO-Objekts bereitgestellt wird, geht die Ausgabe dorthin und das Objekt wird zurückgegeben.
Diese Methode ist voraussichtlich nur auf C Ruby lauffähig. Dies ist eine experimentelle Methode und kann sich ändern. Insbesondere sind die Funktionssignatur und das Ausgabeformat nicht garantiert mit zukünftigen Ruby-Versionen kompatibel.
Source
# 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
Gibt den Inhalt des Ruby-Heaps als JSON aus.
Das Argument output ist dasselbe wie für dump.
full muss ein Boolean sein. Wenn true, werden alle Heap-Slots ausgegeben, einschließlich der leeren (T_NONE).
since muss eine nicht-negative Ganzzahl oder nil sein.
Wenn since eine positive Ganzzahl ist, werden nur Objekte dieser Generation und neuere Generationen ausgegeben. Die aktuelle Generation kann über GC::count abgerufen werden. Objekte, die ohne aktivierte Objektzuweisungsverfolgung zugewiesen wurden, werden ignoriert. Siehe ::trace_object_allocations für weitere Informationen und Beispiele.
Wenn since weggelassen wird oder nil ist, werden alle Objekte ausgegeben.
shapes muss ein Boolean oder eine nicht-negative Ganzzahl sein.
Wenn shapes eine positive Ganzzahl ist, werden nur Formen ausgegeben, die neuer sind als die angegebene Shape-ID. Die aktuelle Shape-ID kann über RubyVM.stat(:next_shape_id) abgerufen werden.
Wenn shapes false ist, werden keine Formen ausgegeben.
Um nur Objekte auszugeben, die nach einem bestimmten Zeitpunkt zugewiesen wurden, können Sie since und shapes kombinieren.
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)
Diese Methode ist voraussichtlich nur auf C Ruby lauffähig. Dies ist eine experimentelle Methode und kann sich ändern. Insbesondere sind die Funktionssignatur und das Ausgabeformat nicht garantiert mit zukünftigen Ruby-Versionen kompatibel.
Source
# 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
Gibt den Inhalt des Ruby-Shape-Baums als JSON aus.
Das Argument output ist dasselbe wie für dump.
Wenn since eine positive Ganzzahl ist, werden nur Formen ausgegeben, die neuer sind als die angegebene Shape-ID. Die aktuelle Shape-ID kann über RubyVM.stat(:next_shape_id) abgerufen werden.
Diese Methode ist voraussichtlich nur auf C Ruby lauffähig. Dies ist eine experimentelle Methode und kann sich ändern. Insbesondere sind die Funktionssignatur und das Ausgabeformat nicht garantiert mit zukünftigen Ruby-Versionen kompatibel.
Private Instanzmethoden
Source
# File gc.rb, line 594 def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false end
Alias von GC.start