diff options
Diffstat (limited to 'ext/objspace/objspace.c')
| -rw-r--r-- | ext/objspace/objspace.c | 245 |
1 files changed, 98 insertions, 147 deletions
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c index 0ead94713a..38bffb07f7 100644 --- a/ext/objspace/objspace.c +++ b/ext/objspace/objspace.c @@ -38,10 +38,11 @@ * information as only a *HINT*. Especially, the size of +T_DATA+ may not be * correct. * - * This method is only expected to work with C Ruby. + * This method is only expected to work with CRuby. * - * From Ruby 2.2, memsize_of(obj) returns a memory size includes - * sizeof(RVALUE). + * From Ruby 3.2 with Variable Width Allocation, it returns the actual slot + * size used plus any additional memory allocated outside the slot (such + * as external strings, arrays, or hash tables). */ static VALUE @@ -107,28 +108,24 @@ each_object_with_flags(each_obj_with_flags cb, void *ctx) /* * call-seq: - * ObjectSpace.memsize_of_all([klass]) -> Integer + * ObjectSpace.memsize_of_all(klass = nil) -> integer * - * Return consuming memory size of all living objects in bytes. + * Returns the total memory size of all living objects in bytes. * - * If +klass+ (should be Class object) is given, return the total memory size - * of instances of the given class. + * ObjectSpace.memsize_of_all # => 12502001 * - * Note that the returned size is incomplete. You need to deal with this - * information as only a *HINT*. Especially, the size of +T_DATA+ may not be - * correct. + * If +klass+ is given (which must be a Class or Module), returns the total + * memory size of objects whose class is, or is a subclass, of +klass+. * - * Note that this method does *NOT* return total malloc'ed memory size. + * class MyClass; end + * ObjectSpace.memsize_of_all(MyClass) # => 0 + * o = MyClass.new + * ObjectSpace.memsize_of_all(MyClass) # => 40 * - * This method can be defined by the following Ruby code: - * - * 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 + * Note that the value returned may be an underestimate of the actual amount + * of memory used. Therefore, the value returned should only be used as a hint, + * rather than a source of truth. In particular, the size of +T_DATA+ objects may + * not be correct. * * This method is only expected to work with C Ruby. */ @@ -140,6 +137,7 @@ memsize_of_all_m(int argc, VALUE *argv, VALUE self) if (argc > 0) { rb_scan_args(argc, argv, "01", &data.klass); + if (!NIL_P(data.klass)) rb_obj_is_kind_of(Qnil, data.klass); } each_object_with_flags(total_i, &data); @@ -223,23 +221,26 @@ type2sym(enum ruby_value_type i) /* * call-seq: - * ObjectSpace.count_objects_size([result_hash]) -> hash + * ObjectSpace.count_objects_size(result_hash = {}) -> result_hash * * Counts objects size (in bytes) for each type. * - * Note that this information is incomplete. You need to deal with - * this information as only a *HINT*. Especially, total size of - * T_DATA may be wrong. + * Note that the returned size may not be accurate, so it should only + * be used as a hint. Specifically, the size for +T_DATA+ may be + * inaccurate because these are custom objects defined in Ruby and + * native extensions and so they may not accurately report their + * memory size. * - * It returns a hash as: - * {:TOTAL=>1461154, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249, ...} + * It returns a hash that looks like: * - * If the optional argument, result_hash, is given, - * it is overwritten and returned. - * This is intended to avoid probe effect. + * {TOTAL: 1461154, T_CLASS: 158280, T_MODULE: 20672, T_STRING: 527249, ...} * - * The contents of the returned hash is implementation defined. - * It may be changed in future. + * The contents of the returned hash are implementation specific and + * may be changed in future versions without notice. + * + * If the optional argument, +result_hash+, is given, + * it is overwritten and returned. + * This is intended to avoid the probe effect. * * This method is only expected to work with C Ruby. */ @@ -294,28 +295,27 @@ size_t rb_sym_immortal_count(void); /* * call-seq: - * ObjectSpace.count_symbols([result_hash]) -> hash + * ObjectSpace.count_symbols(result_hash = nil) -> hash * - * Counts symbols for each Symbol type. + * Returns a hash containing the number of objects for each Symbol type. * - * This method is only for MRI developers interested in performance and memory - * usage of Ruby programs. + * The types of Symbols are the following: * - * If the optional argument, result_hash, is given, it is overwritten and - * returned. This is intended to avoid probe effect. + * - +mortal_dynamic_symbol+: Symbols that are garbage collectable. + * - +immortal_dynamic_symbol+: Symbols that are objects allocated from the + * garbage collector, but are not garbage collectable. + * - +immortal_static_symbol+: Symbols that are not allocated from the + * garbage collector, and are thus not garbage collectable. + * - +immortal_symbol+: the sum of +immortal_dynamic_symbol+ and +immortal_static_symbol+. * - * Note: - * The contents of the returned hash is implementation defined. - * It may be changed in future. + * If the optional argument +result_hash+ is given, it is overwritten and + * returned. This is intended to avoid the probe effect. * - * This method is only expected to work with C Ruby. + * This method is intended for developers interested in performance and memory + * usage of Ruby programs. The contents of the returned hash is implementation + * specific and may change in the future. * - * On this version of MRI, they have 3 types of Symbols (and 1 total counts). - * - * * 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) + * This method is only expected to work with C Ruby. */ static VALUE @@ -335,35 +335,6 @@ count_symbols(int argc, VALUE *argv, VALUE os) return hash; } -/* - * call-seq: - * ObjectSpace.count_nodes([result_hash]) -> hash - * - * Counts nodes for each node type. - * - * This method is only for MRI developers interested in performance and memory - * usage of Ruby programs. - * - * It returns a hash as: - * - * {:NODE_METHOD=>2027, :NODE_FBODY=>1927, :NODE_CFUNC=>1798, ...} - * - * If the optional argument, result_hash, is given, it is overwritten and - * returned. This is intended to avoid probe effect. - * - * Note: - * The contents of the returned hash is implementation defined. - * It may be changed in future. - * - * This method is only expected to work with C Ruby. - */ - -static VALUE -count_nodes(int argc, VALUE *argv, VALUE os) -{ - return setup_hash(argc, argv); -} - static void cto_i(VALUE v, void *data) { @@ -393,32 +364,22 @@ cto_i(VALUE v, void *data) /* * call-seq: - * ObjectSpace.count_tdata_objects([result_hash]) -> hash - * - * Counts objects for each +T_DATA+ type. - * - * This method is only for MRI developers interested in performance and memory - * usage of Ruby programs. - * - * It returns a hash as: + * ObjectSpace.count_tdata_objects(result_hash = nil) -> hash * - * {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. + * Returns a hash containing the number of objects for each +T_DATA+ type. + * The keys are Class objects when the +T_DATA+ object has an associated class, + * or Symbol objects of the name defined in the +rb_data_type_struct+ for internal + * +T_DATA+ objects. * - * If the optional argument, result_hash, is given, it is overwritten and - * returned. This is intended to avoid probe effect. + * ObjectSpace.count_tdata_objects + * # => {RBS::Location => 39255, marshal_compat_table: 1, Encoding => 103, mutex: 1, ... } * - * The contents of the returned hash is implementation specific and may change - * in the future. + * If the optional argument +result_hash+ is given, it is overwritten and + * returned. This is intended to avoid the probe effect. * - * In this version, keys are Class object or Symbol object. - * - * If object is kind of normal (accessible) object, the key is Class object. - * If object is not a kind of normal (internal) object, the key is symbol - * name, registered by rb_data_type_struct. + * This method is intended for developers interested in performance and memory + * usage of Ruby programs. The contents of the returned hash is implementation + * specific and may change in the future. * * This method is only expected to work with C Ruby. */ @@ -457,28 +418,22 @@ count_imemo_objects_i(VALUE v, void *data) /* * call-seq: - * ObjectSpace.count_imemo_objects([result_hash]) -> hash - * - * Counts objects for each +T_IMEMO+ type. - * - * This method is only for MRI developers interested in performance and memory - * usage of Ruby programs. + * ObjectSpace.count_imemo_objects(result_hash = nil) -> hash * - * It returns a hash as: + * Returns a hash containing the number of objects for each +T_IMEMO+ type. + * The keys are Symbol objects of the +T_IMEMO+ type name. + * +T_IMEMO+ objects are Ruby internal objects that are not visible to Ruby + * programs. * - * {:imemo_ifunc=>8, - * :imemo_svar=>7, - * :imemo_cref=>509, - * :imemo_memo=>1, - * :imemo_throw_data=>1} + * ObjectSpace.count_imemo_objects + * # => {imemo_callcache: 5482, imemo_constcache: 1258, imemo_ment: 13906, ... } * - * If the optional argument, result_hash, is given, it is overwritten and - * returned. This is intended to avoid probe effect. + * If the optional argument +result_hash+ is given, it is overwritten and + * returned. This is intended to avoid the probe effect. * - * The contents of the returned hash is implementation specific and may change - * in the future. - * - * In this version, keys are symbol objects. + * This method is intended for developers interested in performance and memory + * usage of Ruby programs. The contents of the returned hash is implementation + * specific and may change in the future. * * This method is only expected to work with C Ruby. */ @@ -499,11 +454,13 @@ count_imemo_objects(int argc, VALUE *argv, VALUE self) 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_cvar_entry); INIT_IMEMO_TYPE_ID(imemo_callinfo); INIT_IMEMO_TYPE_ID(imemo_callcache); INIT_IMEMO_TYPE_ID(imemo_constcache); + INIT_IMEMO_TYPE_ID(imemo_fields); + INIT_IMEMO_TYPE_ID(imemo_subclasses); + INIT_IMEMO_TYPE_ID(imemo_cdhash); #undef INIT_IMEMO_TYPE_ID } @@ -602,42 +559,37 @@ collect_values(st_data_t key, st_data_t value, st_data_t data) * call-seq: * ObjectSpace.reachable_objects_from(obj) -> array or nil * - * [MRI specific feature] Return all reachable objects from `obj'. + * Returns all reachable objects from +obj+ as an array: * - * This method returns all reachable objects from `obj'. + * ObjectSpace.reachable_objects_from(['a', 'b', 'c']) + * #=> [Array, 'a', 'b', 'c'] * - * If `obj' has two or more references to the same object `x', then returned - * array only includes one `x' object. + * The returned array is deduplicated, meaning that if +obj+ refers + * to another object more than once, it will only be added to the array + * once: * - * If `obj' is a non-markable (non-heap management) object such as true, - * false, nil, symbols and Fixnums (and Flonum) then it simply returns nil. + * ObjectSpace.reachable_objects_from([v = 'a', v, v]) + * #=> [Array, 'a'] * - * If `obj' has references to an internal object, then it returns instances of - * ObjectSpace::InternalObjectWrapper class. This object contains a reference - * to an internal object and you can check the type of internal object with - * `type' method. + * Returns +nil+ if +obj+ is not a markable object (i.e. non-heap + * managed) object. Non-markable objects include +true+, +false+, + * +nil+, certain symbols, small integers, and floats: * - * If `obj' is instance of ObjectSpace::InternalObjectWrapper class, then this - * method returns all reachable object from an internal object, which is - * pointed by `obj'. + * ObjectSpace.reachable_objects_from(1) + * #=> nil * - * With this method, you can find memory leaks. + * All references to internal objects in the returned array are wrapped + * using ObjectSpace::InternalObjectWrapper objects. This object contains + * a reference to the internal object and the type of the object can + * be accessed using the ObjectSpace::InternalObjectWrapper#type method. * - * This method is only expected to work with C Ruby. + * If +obj+ is instance of ObjectSpace::InternalObjectWrapper, then this + * method returns all reachable object from the internal object. * - * Example: - * 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 + * This method is useful for debugging purposes, such as finding + * memory leaks. * + * This method is only expected to work with C Ruby. */ static VALUE @@ -792,7 +744,7 @@ objspace_internal_super_of(VALUE self, VALUE obj) case T_MODULE: case T_CLASS: case T_ICLASS: - super = RCLASS_SUPER(obj); + super = rb_class_super_of(obj); break; default: rb_raise(rb_eArgError, "class or module is expected"); @@ -834,7 +786,6 @@ Init_objspace(void) rb_define_module_function(rb_mObjSpace, "count_objects_size", count_objects_size, -1); rb_define_module_function(rb_mObjSpace, "count_symbols", count_symbols, -1); - rb_define_module_function(rb_mObjSpace, "count_nodes", count_nodes, -1); rb_define_module_function(rb_mObjSpace, "count_tdata_objects", count_tdata_objects, -1); rb_define_module_function(rb_mObjSpace, "count_imemo_objects", count_imemo_objects, -1); |
