From 338c8538c92a1f3c4117fb920855a610cfaefc25 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Thu, 9 Jul 2020 18:52:31 -0700 Subject: Initial ObjectSpace.memsize_of implementation --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 201 ++++++++++++++++++++++ 1 file changed, 201 insertions(+) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index b89fb0580..fe7e929c8 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -2,6 +2,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include struct os_count_struct { mrb_int total; @@ -168,12 +176,205 @@ os_each_object(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(d.count); } +static void os_memsize_of_object(mrb_state*,mrb_value,mrb_bool,mrb_int*); + +static int +os_memsize_ivar_cb(mrb_state *mrb, mrb_sym _name, mrb_value obj, void *data) +{ + mrb_int *cb_data = (mrb_int *)data; + mrb_int recurse = *(&cb_data[0]); + mrb_int* total = &cb_data[1]; + + os_memsize_of_object(mrb, obj, (mrb_bool)(recurse), total); + return 0; +} + +static void +os_memsize_of_ivars(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int *t) +{ + /* need iv segment table size */ + if(recurse) { + mrb_int r = (mrb_int)recurse; + mrb_int *cb_data[2] = { &r, t }; + mrb_iv_foreach(mrb, obj, os_memsize_ivar_cb, t); + } +} + +static void +os_memsize_of_irep(mrb_state* state, struct mrb_irep *irep, mrb_int* t) +{ + mrb_int i; + (*t) += (irep->slen * sizeof(mrb_sym)) + + (irep->plen * sizeof(mrb_code)) + + (irep->ilen * sizeof(mrb_code)); + + for(i = 0; i < irep->rlen; i++) { + os_memsize_of_irep(state, irep->reps[i], t); + } +} + +static void +os_memsize_of_method(mrb_state* mrb, mrb_value method_obj, mrb_int* t) +{ + mrb_value proc_value = mrb_obj_iv_get(mrb, mrb_obj_ptr(method_obj), + mrb_intern_lit(mrb, "_proc")); + struct RProc *proc = mrb_proc_ptr(proc_value); + + (*t) += sizeof(struct RProc); + if(!MRB_PROC_CFUNC_P(proc)) os_memsize_of_irep(mrb, proc->body.irep, t); +} + +static void +os_memsize_of_methods(mrb_state* mrb, mrb_value obj, mrb_int* t) +{ + mrb_value method_list; + mrb_int i; + if(!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "instance_methods"))) return; + method_list = mrb_funcall(mrb, obj, "instance_methods", 1, mrb_false_value()); + for(i = 0; i < RARRAY_LEN(method_list); i++) { + mrb_value method = mrb_funcall(mrb, obj, "instance_method", 1, + mrb_ary_ref(mrb, method_list, i)); + os_memsize_of_method(mrb, method, t); + } +} + +static void +os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t) +{ + switch(obj.tt) { + case MRB_TT_STRING: + (*t) += RSTRING_LEN(obj); + break; + case MRB_TT_CLASS: + case MRB_TT_MODULE: + case MRB_TT_EXCEPTION: + case MRB_TT_SCLASS: + case MRB_TT_ICLASS: + case MRB_TT_OBJECT: { + os_memsize_of_ivars(mrb, obj, recurse, t); + if(mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod"))) { + os_memsize_of_method(mrb, obj, t); + } + else { + os_memsize_of_methods(mrb, obj, t); + } + break; + } + case MRB_TT_HASH: { + struct htable* htable = RHASH_TBL(obj); + /* Need htable & segment struct defs */ + break; + } + case MRB_TT_ARRAY: { + mrb_int len, i; + len = RARRAY_LEN(obj); + /* Arrays that do not fit within an RArray perform a heap allocation + * storing an array of pointers to the original objects*/ + if(len > MRB_ARY_EMBED_LEN_MAX) (*t) += sizeof(mrb_value *) * len; + + if(recurse) { + for(i = 0; i < len; i++) { + os_memsize_of_object(mrb, ARY_PTR(mrb_ary_ptr(obj))[i], recurse, t); + } + } + break; + } + case MRB_TT_PROC: { + struct RProc* proc = mrb_proc_ptr(obj); + (*t) += MRB_ENV_LEN(proc->e.env) * sizeof(mrb_value); + if(!MRB_PROC_CFUNC_P(proc)) os_memsize_of_irep(mrb, proc->body.irep, t); + break; + } + case MRB_TT_DATA: + if(mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "memsize"))) { + (*t) += mrb_fixnum(mrb_funcall(mrb, obj, "memsize", 0)); + } + break; + #ifndef MRB_WITHOUT_FLOAT + case MRB_TT_FLOAT: + #ifdef MRB_WORD_BOXING + (*t) += sizeof(struct RFloat); + #endif + break; + #endif + case MRB_TT_RANGE: + #ifndef MRB_RANGE_EMBED + (*t) += sizeof(struct mrb_range_edges); + #endif + break; + case MRB_TT_FIBER: + struct RFiber* fiber = (struct RFiber*)mrb_ptr(obj); + (*t) += sizeof(struct mrb_context); + break; + /* zero heap size types. + * immediate VM stack values, contained within mrb_state, mrb_heap_page, + * or on C stack */ + case MRB_TT_TRUE: + case MRB_TT_FALSE: + case MRB_TT_FIXNUM: + case MRB_TT_BREAK: + case MRB_TT_CPTR: + case MRB_TT_SYMBOL: + case MRB_TT_FREE: + case MRB_TT_UNDEF: + case MRB_TT_ENV: + case MRB_TT_ISTRUCT: + /* never used, silences compiler warning + * not having a default: clause lets the compiler tell us when there is a new + * TT not accounted for */ + case MRB_TT_MAXDEFINE: + break; + } +} + +/* + * call-seq: + * ObjectSpace.memsize_of(obj, recurse: false) -> Numeric + * + * Returns the amount of heap memory allocated for object in size_t units. + * Not all objects cause additional heap allocations beyond their object pointer + * in the heap page and may return 0. + * + * The return value depends on the definition of size_t on that platform, + * therefore the value is not comparable across platform types. + * + * Immediate values such as integers, booleans, symbols and unboxed float numbers + * return 0. Additionally special objects which are small enough to fit inside an + * object * pointer, termed embedded objects, also return 0. Strings and arrays + * below a compile-time defined size may be embedded. + * + * Setting recurse: true descends into instance variables, array members, + * and hash values recursively, calculating the child objects and adding to + * the final sum. + * + */ + +static mrb_value +os_memsize_of(mrb_state *mrb, mrb_value self) +{ + mrb_int total; + mrb_value obj; + mrb_bool recurse; + const char *kw_names[1] = { "recurse" }; + mrb_value kw_values[1]; + const mrb_kwargs kwargs = { 1, kw_values, kw_names, 0, NULL }; + + mrb_get_args(mrb, "o:", &obj, &kwargs); + recurse = mrb_obj_eq(mrb, kw_values[0], mrb_true_value()) ? TRUE : FALSE; + + total = 0; + os_memsize_of_object(mrb, obj, recurse, &total); + + return mrb_fixnum_value(total); +} + void mrb_mruby_objectspace_gem_init(mrb_state *mrb) { struct RClass *os = mrb_define_module(mrb, "ObjectSpace"); mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_OPT(1)); mrb_define_class_method(mrb, os, "each_object", os_each_object, MRB_ARGS_OPT(1)); + mrb_define_class_method(mrb, os, "memsize_of", os_memsize_of, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); } void -- cgit v1.2.3 From 37d662868807615a2b8f0f3e3939f592e2b43835 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Fri, 10 Jul 2020 00:57:45 -0700 Subject: fix case scopes and variable names --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index fe7e929c8..c0bc2b807 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -196,7 +196,7 @@ os_memsize_of_ivars(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int *t) if(recurse) { mrb_int r = (mrb_int)recurse; mrb_int *cb_data[2] = { &r, t }; - mrb_iv_foreach(mrb, obj, os_memsize_ivar_cb, t); + mrb_iv_foreach(mrb, obj, os_memsize_ivar_cb, cb_data); } } @@ -261,8 +261,8 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t break; } case MRB_TT_HASH: { - struct htable* htable = RHASH_TBL(obj); - /* Need htable & segment struct defs */ + /*struct htable* htable = RHASH_TBL(obj); + * Need htable & segment struct defs */ break; } case MRB_TT_ARRAY: { @@ -302,10 +302,11 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t (*t) += sizeof(struct mrb_range_edges); #endif break; - case MRB_TT_FIBER: - struct RFiber* fiber = (struct RFiber*)mrb_ptr(obj); + case MRB_TT_FIBER: { + /* struct RFiber* fiber = (struct RFiber*)mrb_ptr(obj); */ (*t) += sizeof(struct mrb_context); break; + } /* zero heap size types. * immediate VM stack values, contained within mrb_state, mrb_heap_page, * or on C stack */ -- cgit v1.2.3 From 41e3220539ff0150bb09968b243ce6ed96b6fe0e Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 13 Jul 2020 15:56:27 -0700 Subject: All values use page slot size in calculation --- include/mruby/gc.h | 1 + mrbgems/mruby-objectspace/src/mruby_objectspace.c | 16 +++++++++++----- src/gc.c | 7 +++++++ 3 files changed, 19 insertions(+), 5 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/include/mruby/gc.h b/include/mruby/gc.h index 4d9fb60eb..3b2ded9d4 100644 --- a/include/mruby/gc.h +++ b/include/mruby/gc.h @@ -21,6 +21,7 @@ struct mrb_state; #define MRB_EACH_OBJ_BREAK 1 typedef int (mrb_each_object_callback)(struct mrb_state *mrb, struct RBasic *obj, void *data); void mrb_objspace_each_objects(struct mrb_state *mrb, mrb_each_object_callback *callback, void *data); +const mrb_int mrb_objspace_page_slot_size(); MRB_API void mrb_free_context(struct mrb_state *mrb, struct mrb_context *c); #ifndef MRB_GC_ARENA_SIZE diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index c0bc2b807..791bf68fe 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -251,6 +251,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t case MRB_TT_SCLASS: case MRB_TT_ICLASS: case MRB_TT_OBJECT: { + (*t) += mrb_objspace_page_slot_size(); os_memsize_of_ivars(mrb, obj, recurse, t); if(mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod"))) { os_memsize_of_method(mrb, obj, t); @@ -270,6 +271,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t len = RARRAY_LEN(obj); /* Arrays that do not fit within an RArray perform a heap allocation * storing an array of pointers to the original objects*/ + (*t) += mrb_objspace_page_slot_size(); if(len > MRB_ARY_EMBED_LEN_MAX) (*t) += sizeof(mrb_value *) * len; if(recurse) { @@ -280,12 +282,14 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t break; } case MRB_TT_PROC: { + (*t) += mrb_objspace_page_slot_size(); struct RProc* proc = mrb_proc_ptr(obj); (*t) += MRB_ENV_LEN(proc->e.env) * sizeof(mrb_value); if(!MRB_PROC_CFUNC_P(proc)) os_memsize_of_irep(mrb, proc->body.irep, t); break; } case MRB_TT_DATA: + (*t) += mrb_objspace_page_slot_size(); if(mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "memsize"))) { (*t) += mrb_fixnum(mrb_funcall(mrb, obj, "memsize", 0)); } @@ -293,23 +297,25 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: #ifdef MRB_WORD_BOXING - (*t) += sizeof(struct RFloat); + (*t) += mrb_objspace_page_slot_size() + + sizeof(struct RFloat); #endif break; #endif case MRB_TT_RANGE: #ifndef MRB_RANGE_EMBED - (*t) += sizeof(struct mrb_range_edges); + (*t) += mrb_objspace_page_slot_size() + + sizeof(struct mrb_range_edges); #endif break; case MRB_TT_FIBER: { /* struct RFiber* fiber = (struct RFiber*)mrb_ptr(obj); */ (*t) += sizeof(struct mrb_context); + case MRB_TT_ISTRUCT: + (*t) += mrb_objspace_page_slot_size(); break; - } /* zero heap size types. - * immediate VM stack values, contained within mrb_state, mrb_heap_page, - * or on C stack */ + * immediate VM stack values, contained within mrb_state, or on C stack */ case MRB_TT_TRUE: case MRB_TT_FALSE: case MRB_TT_FIXNUM: diff --git a/src/gc.c b/src/gc.c index e1892080f..fd4fb2406 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1599,6 +1599,13 @@ mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, vo } } +const mrb_int +mrb_objspace_page_slot_size() +{ + const mrb_int i = sizeof(RVALUE); + return i; +} + #ifdef GC_TEST #ifdef GC_DEBUG static mrb_value gc_test(mrb_state *, mrb_value); -- cgit v1.2.3 From e7bd7d0eaf677f62d86f27c2e9a917faa5a7d419 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 13 Jul 2020 15:58:50 -0700 Subject: Use size of hash's table in calculation --- include/mruby/hash.h | 1 + mrbgems/mruby-objectspace/src/mruby_objectspace.c | 9 ++++++--- src/hash.c | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/include/mruby/hash.h b/include/mruby/hash.h index 0052a1105..cd53f6aeb 100644 --- a/include/mruby/hash.h +++ b/include/mruby/hash.h @@ -23,6 +23,7 @@ struct RHash { #define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v))) #define mrb_hash_value(p) mrb_obj_value((void*)(p)) +mrb_int os_memsize_of_hash_table(mrb_value obj); MRB_API mrb_value mrb_hash_new_capa(mrb_state *mrb, mrb_int capa); MRB_API mrb_value mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash); MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash); diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 791bf68fe..b0a3e0d89 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -262,8 +262,12 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t break; } case MRB_TT_HASH: { - /*struct htable* htable = RHASH_TBL(obj); - * Need htable & segment struct defs */ + (*t) += mrb_objspace_page_slot_size() + + os_memsize_of_hash_table(obj); + if(recurse) { + os_memsize_of_object(mrb, mrb_hash_keys(mrb, obj), recurse, t); + os_memsize_of_object(mrb, mrb_hash_values(mrb, obj), recurse, t); + } break; } case MRB_TT_ARRAY: { @@ -325,7 +329,6 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t case MRB_TT_FREE: case MRB_TT_UNDEF: case MRB_TT_ENV: - case MRB_TT_ISTRUCT: /* never used, silences compiler warning * not having a default: clause lets the compiler tell us when there is a new * TT not accounted for */ diff --git a/src/hash.c b/src/hash.c index 4d5310903..7c90758c0 100644 --- a/src/hash.c +++ b/src/hash.c @@ -518,6 +518,20 @@ ht_foreach(mrb_state *mrb, htable *t, mrb_hash_foreach_func *func, void *p) } } +mrb_int +os_memsize_of_hash_table(mrb_value obj) +{ + struct htable *h = mrb_hash_ptr(obj)->ht; + mrb_int segkv_size = 0; + + if(h->index) segkv_size = (sizeof(struct segkv) * h->index->capa); + + return sizeof(htable) + + sizeof(segindex) + + (sizeof(segment) * h->size) + + segkv_size; +} + /* Iterates over the hash table. */ MRB_API void mrb_hash_foreach(mrb_state *mrb, struct RHash *hash, mrb_hash_foreach_func *func, void *p) -- cgit v1.2.3 From 6f945a09b4a09828667da6d4bad85b8ef50baf9c Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 13 Jul 2020 15:59:24 -0700 Subject: Use object iv table size in calculation --- include/mruby/variable.h | 1 + mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- src/variable.c | 9 +++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/include/mruby/variable.h b/include/mruby/variable.h index 6e918cf57..5559f6606 100644 --- a/include/mruby/variable.h +++ b/include/mruby/variable.h @@ -35,6 +35,7 @@ mrb_value mrb_vm_cv_get(mrb_state*, mrb_sym); void mrb_vm_cv_set(mrb_state*, mrb_sym, mrb_value); mrb_value mrb_vm_const_get(mrb_state*, mrb_sym); void mrb_vm_const_set(mrb_state*, mrb_sym, mrb_value); +mrb_int mrb_obj_iv_tbl_memsize(mrb_state*, mrb_value); MRB_API mrb_value mrb_const_get(mrb_state*, mrb_value, mrb_sym); MRB_API void mrb_const_set(mrb_state*, mrb_value, mrb_sym, mrb_value); MRB_API mrb_bool mrb_const_defined(mrb_state*, mrb_value, mrb_sym); diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index b0a3e0d89..e48ac5b11 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -192,7 +192,7 @@ os_memsize_ivar_cb(mrb_state *mrb, mrb_sym _name, mrb_value obj, void *data) static void os_memsize_of_ivars(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int *t) { - /* need iv segment table size */ + (*t) += mrb_obj_iv_tbl_memsize(mrb, obj); if(recurse) { mrb_int r = (mrb_int)recurse; mrb_int *cb_data[2] = { &r, t }; diff --git a/src/variable.c b/src/variable.c index 030aa7b00..0755f7d92 100644 --- a/src/variable.c +++ b/src/variable.c @@ -4,6 +4,7 @@ ** See Copyright Notice in mruby.h */ +#include #include #include #include @@ -1128,6 +1129,14 @@ mrb_class_find_path(mrb_state *mrb, struct RClass *c) return path; } +mrb_int +mrb_obj_iv_tbl_memsize(mrb_state* mrb, mrb_value obj) +{ + return sizeof(iv_tbl) + + (sizeof(segment) * ceil(iv_size(mrb, mrb_obj_ptr(obj)->iv)/ + MRB_IV_SEGMENT_SIZE)); +} + #define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c)) mrb_bool -- cgit v1.2.3 From 5184263bdcdef9e467cf67b71be46368bc5409d2 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 13 Jul 2020 16:00:14 -0700 Subject: Calculating sizes of VM components for a Fiber --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 27 ++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index e48ac5b11..0ffce2fbc 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -312,9 +312,30 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t sizeof(struct mrb_range_edges); #endif break; - case MRB_TT_FIBER: { - /* struct RFiber* fiber = (struct RFiber*)mrb_ptr(obj); */ - (*t) += sizeof(struct mrb_context); + case MRB_TT_FIBER: + struct RFiber* f = (struct RFiber *)mrb_ptr(obj); + mrb_callinfo *ci_p = f->cxt->cibase; + ptrdiff_t stack_size = f->cxt->stend - f->cxt->stbase; + ptrdiff_t ci_size = f->cxt->ciend - f->cxt->cibase; + mrb_int i = 0; + + while(ci_p < f->cxt->ciend) { + if(ci_p->proc) os_memsize_of_irep(mrb, ci_p->proc->body.irep, t); + ci_p++; + } + + for(i = 0; i <= f->cxt->esize; i++) { + os_memsize_of_irep(mrb, f->cxt->ensure[i]->body.irep, t); + } + + (*t) += mrb_objspace_page_slot_size() + + sizeof(struct RFiber) + + sizeof(struct mrb_context) + + sizeof(struct RProc *) * f->cxt->esize + + sizeof(uint16_t *) * f->cxt->rsize + + stack_size + + ci_size; + break; case MRB_TT_ISTRUCT: (*t) += mrb_objspace_page_slot_size(); break; -- cgit v1.2.3 From ad4402159119d61d3a0b0a997b219bc1a0f4f196 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 13 Jul 2020 16:43:59 -0700 Subject: C89 compiler mode fixes --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 0ffce2fbc..f28336b95 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -286,8 +286,8 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t break; } case MRB_TT_PROC: { - (*t) += mrb_objspace_page_slot_size(); struct RProc* proc = mrb_proc_ptr(obj); + (*t) += mrb_objspace_page_slot_size(); (*t) += MRB_ENV_LEN(proc->e.env) * sizeof(mrb_value); if(!MRB_PROC_CFUNC_P(proc)) os_memsize_of_irep(mrb, proc->body.irep, t); break; @@ -312,7 +312,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t sizeof(struct mrb_range_edges); #endif break; - case MRB_TT_FIBER: + case MRB_TT_FIBER: { struct RFiber* f = (struct RFiber *)mrb_ptr(obj); mrb_callinfo *ci_p = f->cxt->cibase; ptrdiff_t stack_size = f->cxt->stend - f->cxt->stbase; @@ -336,6 +336,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t stack_size + ci_size; break; + } case MRB_TT_ISTRUCT: (*t) += mrb_objspace_page_slot_size(); break; -- cgit v1.2.3 From 0e5394638bd6f8fa8c52fa4f75c4c1799adb70e0 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 13 Jul 2020 17:05:03 -0700 Subject: Validate ensure stack presense before calculating --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index f28336b95..d5ffa83f1 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -324,8 +324,10 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t ci_p++; } - for(i = 0; i <= f->cxt->esize; i++) { - os_memsize_of_irep(mrb, f->cxt->ensure[i]->body.irep, t); + if(f->cxt->esize) { + for(i = 0; i <= f->cxt->esize; i++) { + os_memsize_of_irep(mrb, f->cxt->ensure[i]->body.irep, t); + } } (*t) += mrb_objspace_page_slot_size() + -- cgit v1.2.3 From 4d32c671a70cd066010cf502ab13ab8f78357d0e Mon Sep 17 00:00:00 2001 From: Rory O'Connell <19547+RoryO@users.noreply.github.com> Date: Tue, 14 Jul 2020 23:30:35 -0700 Subject: Finishing out memsize_of recursion --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 39 +++++++----- mrbgems/mruby-objectspace/test/objectspace.rb | 73 ++++++++++++++++++++++- 2 files changed, 93 insertions(+), 19 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index d5ffa83f1..7088e166f 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -176,27 +176,28 @@ os_each_object(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(d.count); } -static void os_memsize_of_object(mrb_state*,mrb_value,mrb_bool,mrb_int*); +static void os_memsize_of_object(mrb_state*,mrb_value,mrb_value,mrb_int*); + +struct os_memsize_cb_data { + mrb_int *t; + mrb_value recurse; +}; static int os_memsize_ivar_cb(mrb_state *mrb, mrb_sym _name, mrb_value obj, void *data) { - mrb_int *cb_data = (mrb_int *)data; - mrb_int recurse = *(&cb_data[0]); - mrb_int* total = &cb_data[1]; - - os_memsize_of_object(mrb, obj, (mrb_bool)(recurse), total); + struct os_memsize_cb_data *cb_data = (struct os_memsize_cb_data *)(data); + os_memsize_of_object(mrb, obj, cb_data->recurse, cb_data->t); return 0; } static void -os_memsize_of_ivars(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int *t) +os_memsize_of_ivars(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int *t) { (*t) += mrb_obj_iv_tbl_memsize(mrb, obj); - if(recurse) { - mrb_int r = (mrb_int)recurse; - mrb_int *cb_data[2] = { &r, t }; - mrb_iv_foreach(mrb, obj, os_memsize_ivar_cb, cb_data); + if(!mrb_nil_p(recurse)) { + struct os_memsize_cb_data cb_data = {t, recurse}; + mrb_iv_foreach(mrb, obj, os_memsize_ivar_cb, &cb_data); } } @@ -239,8 +240,14 @@ os_memsize_of_methods(mrb_state* mrb, mrb_value obj, mrb_int* t) } static void -os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t) +os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* t) { + if(!mrb_nil_p(recurse)) { + const mrb_value obj_id = mrb_fixnum_value(mrb_obj_id(obj)); + if(mrb_hash_key_p(mrb, recurse, obj_id)) return; + mrb_hash_set(mrb, recurse, obj_id, mrb_true_value()); + } + switch(obj.tt) { case MRB_TT_STRING: (*t) += RSTRING_LEN(obj); @@ -264,7 +271,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t case MRB_TT_HASH: { (*t) += mrb_objspace_page_slot_size() + os_memsize_of_hash_table(obj); - if(recurse) { + if(!mrb_nil_p(recurse)) { os_memsize_of_object(mrb, mrb_hash_keys(mrb, obj), recurse, t); os_memsize_of_object(mrb, mrb_hash_values(mrb, obj), recurse, t); } @@ -278,7 +285,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t (*t) += mrb_objspace_page_slot_size(); if(len > MRB_ARY_EMBED_LEN_MAX) (*t) += sizeof(mrb_value *) * len; - if(recurse) { + if(!mrb_nil_p(recurse)) { for(i = 0; i < len; i++) { os_memsize_of_object(mrb, ARY_PTR(mrb_ary_ptr(obj))[i], recurse, t); } @@ -388,13 +395,13 @@ os_memsize_of(mrb_state *mrb, mrb_value self) { mrb_int total; mrb_value obj; - mrb_bool recurse; + mrb_value recurse; const char *kw_names[1] = { "recurse" }; mrb_value kw_values[1]; const mrb_kwargs kwargs = { 1, kw_values, kw_names, 0, NULL }; mrb_get_args(mrb, "o:", &obj, &kwargs); - recurse = mrb_obj_eq(mrb, kw_values[0], mrb_true_value()) ? TRUE : FALSE; + recurse = mrb_obj_eq(mrb, kw_values[0], mrb_true_value())? mrb_hash_new(mrb) : mrb_nil_value(); total = 0; os_memsize_of_object(mrb, obj, recurse, &total); diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb index 60626e6bf..610cdfbfa 100644 --- a/mrbgems/mruby-objectspace/test/objectspace.rb +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -123,15 +123,82 @@ assert 'ObjectSpace.memsize_of' do assert_not_equal m_size, 0, 'method size not zero' # collections - assert_not_equal ObjectSpace.memsize_of([]), 0, 'empty array size not zero' - assert_not_equal ObjectSpace.memsize_of(Array.new(16)), 0, 'array size not zero' + empty_array_size = ObjectSpace.memsize_of [] + assert_not_equal empty_array_size, 0, 'empty array size not zero' + assert_operator empty_array_size, :<, ObjectSpace.memsize_of(Array.new(16)), 'large array size greater than embed' # fiber - assert_not_equal ObjectSpace.memsize_of(Fiber.new {}), 0, 'fiber not zero' + empty_fiber_size = ObjectSpace.memsize_of(Fiber.new {}) + assert_not_equal empty_fiber_size, 0, 'empty fiber not zero' + assert_operator empty_fiber_size, :<, ObjectSpace.memsize_of(Fiber.new { yield; 1 }), 'Fiber code size growth' #hash assert_not_equal ObjectSpace.memsize_of({}), 0, 'empty hash size not zero' # recursion + foo_str = 'foo' * 10 + bar_str = 'bar' * 10 + caz_str = 'caz' * 10 + fbc_ary = [foo_str, bar_str, caz_str] + assert_operator ObjectSpace.memsize_of(fbc_ary), + :<, + ObjectSpace.memsize_of(fbc_ary, recurse: true), + 'basic array recursion' + + big_ary = [ 'a' * 10, + [ 'b' * 10, + [ 'c' * 10, + [ 'd' * 10, + [ 'e' * 10, + [ 'f' * 10, + ['g' * 10] + ] * 10, + ] * 10, + ] * 10, + ] * 10, + ] * 10, + ] * 10 + assert_operator ObjectSpace.memsize_of(big_ary), + :<, + ObjectSpace.memsize_of(big_ary, recurse: true), + 'large array recursion' + + assert_nothing_raised 'infinite array recursion' do + ObjectSpace.memsize_of(fbc_ary.push(fbc_ary)) + end + + basic_hsh = {a: [foo_str, bar_str], b: caz_str, 'c' => {}} + assert_operator ObjectSpace.memsize_of(basic_hsh), + :<, + ObjectSpace.memsize_of(basic_hsh, recurse: true), + 'hash recursion with basic keys' + + weird_keys = {big_ary => foo_str} + assert_operator ObjectSpace.memsize_of(weird_keys), + :<, + ObjectSpace.memsize_of(weird_keys, recurse: true), + 'hash recursion with collection as key' + + basic_hsh.store('d', basic_hsh) + assert_nothing_raised 'hash value recursion' do + ObjectSpace.memsize_of basic_hsh, recurse: true + end + + foo_klass = Class.new do + def bar= b + @bar = b + end + end + fk_one = foo_klass.new + fk_one.bar = fbc_ary + assert_operator ObjectSpace.memsize_of(fk_one), + :<, + ObjectSpace.memsize_of(fk_one, recurse: true), + 'basic ivar recursion' + + fk_one.bar = fk_one + assert_nothing_raised 'ivar infinite recursion' do + ObjectSpace.memsize_of(fk_one, recurse: true) + end end -- cgit v1.2.3 From 38b0759108882c4d791cc4cf1a5989fb8e5d533d Mon Sep 17 00:00:00 2001 From: Rory O'Connell <19547+RoryO@users.noreply.github.com> Date: Tue, 14 Jul 2020 23:43:10 -0700 Subject: Clarify memsize_of documentation --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 7088e166f..9fbfd0d54 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -373,20 +373,24 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* * ObjectSpace.memsize_of(obj, recurse: false) -> Numeric * * Returns the amount of heap memory allocated for object in size_t units. - * Not all objects cause additional heap allocations beyond their object pointer - * in the heap page and may return 0. * * The return value depends on the definition of size_t on that platform, * therefore the value is not comparable across platform types. * * Immediate values such as integers, booleans, symbols and unboxed float numbers * return 0. Additionally special objects which are small enough to fit inside an - * object * pointer, termed embedded objects, also return 0. Strings and arrays - * below a compile-time defined size may be embedded. + * object pointer, termed embedded objects, will return the size of the object pointer. + * Strings and arrays below a compile-time defined size may be embedded. * * Setting recurse: true descends into instance variables, array members, - * and hash values recursively, calculating the child objects and adding to - * the final sum. + * hash keys and hash values recursively, calculating the child objects and adding to + * the final sum. It avoids infinite recursion and over counting objects by + * internally tracking discovered object ids. + * + * MRB_TT_DATA objects aren't calculated beyond their original page slot. However, + * if the object implements a memsize method it will call that method and add the + * return value to the total. This provides an opportunity for C based data structures + * to report their memory usage. * */ -- cgit v1.2.3 From f74d370c1574fba53330c032ec6ac4716fee4a07 Mon Sep 17 00:00:00 2001 From: Rory O'Connell <19547+RoryO@users.noreply.github.com> Date: Wed, 15 Jul 2020 19:57:22 -0700 Subject: mrb_ prefix convention --- include/mruby/hash.h | 2 +- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- src/hash.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/include/mruby/hash.h b/include/mruby/hash.h index cd53f6aeb..04b265ec3 100644 --- a/include/mruby/hash.h +++ b/include/mruby/hash.h @@ -23,7 +23,7 @@ struct RHash { #define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v))) #define mrb_hash_value(p) mrb_obj_value((void*)(p)) -mrb_int os_memsize_of_hash_table(mrb_value obj); +mrb_int mrb_os_memsize_of_hash_table(mrb_value obj); MRB_API mrb_value mrb_hash_new_capa(mrb_state *mrb, mrb_int capa); MRB_API mrb_value mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash); MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash); diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 9fbfd0d54..7892c6a1b 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -270,7 +270,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* } case MRB_TT_HASH: { (*t) += mrb_objspace_page_slot_size() + - os_memsize_of_hash_table(obj); + mrb_os_memsize_of_hash_table(obj); if(!mrb_nil_p(recurse)) { os_memsize_of_object(mrb, mrb_hash_keys(mrb, obj), recurse, t); os_memsize_of_object(mrb, mrb_hash_values(mrb, obj), recurse, t); diff --git a/src/hash.c b/src/hash.c index 7c90758c0..79b61d8b2 100644 --- a/src/hash.c +++ b/src/hash.c @@ -519,7 +519,7 @@ ht_foreach(mrb_state *mrb, htable *t, mrb_hash_foreach_func *func, void *p) } mrb_int -os_memsize_of_hash_table(mrb_value obj) +mrb_os_memsize_of_hash_table(mrb_value obj) { struct htable *h = mrb_hash_ptr(obj)->ht; mrb_int segkv_size = 0; -- cgit v1.2.3 From 7f66cf7d66f71d729f9ad1b129d9d817c075b979 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 10:51:01 +0900 Subject: Fix `memsize_of` for string objects; #5032 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 7892c6a1b..a9469203f 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -250,7 +250,10 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* switch(obj.tt) { case MRB_TT_STRING: - (*t) += RSTRING_LEN(obj); + (*t) += mrb_objspace_page_slot_size(); + if (!RSTR_EMBED_P(RSTRING(obj)) && !RSTR_SHARED_P(RSTRING(obj))) { + (*t) += RSTRING_CAPA(obj); + } break; case MRB_TT_CLASS: case MRB_TT_MODULE: -- cgit v1.2.3 From c6b8b58e0e1ad8a06e28d97bcc5860a14246537b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 10:52:04 +0900 Subject: Fix `memsize_of` for fiber objects; #5032 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index a9469203f..a67697d0d 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -345,8 +345,8 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* sizeof(struct mrb_context) + sizeof(struct RProc *) * f->cxt->esize + sizeof(uint16_t *) * f->cxt->rsize + - stack_size + - ci_size; + sizeof(mrb_value) * stack_size + + sizeof(mrb_callinfo) * ci_size; break; } case MRB_TT_ISTRUCT: -- cgit v1.2.3 From 60279b2a8ed3f1c802371ecb2450da63e78316bc Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 10:53:24 +0900 Subject: Use `mrb_test` instead of `mrb_obj_eq`; #5032 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index a67697d0d..8892f40dc 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -408,7 +408,7 @@ os_memsize_of(mrb_state *mrb, mrb_value self) const mrb_kwargs kwargs = { 1, kw_values, kw_names, 0, NULL }; mrb_get_args(mrb, "o:", &obj, &kwargs); - recurse = mrb_obj_eq(mrb, kw_values[0], mrb_true_value())? mrb_hash_new(mrb) : mrb_nil_value(); + recurse = (!mrb_undef_p(kw_values[0]) && mrb_test(kw_values[0]))? mrb_hash_new(mrb) : mrb_nil_value(); total = 0; os_memsize_of_object(mrb, obj, recurse, &total); -- cgit v1.2.3 From 2e56da5a78befb93a1e4debe42d783c4b7be4c30 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 10:59:43 +0900 Subject: Remove `MRB_TT_DATA` calculation of `memsize_of`; #5032 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 8892f40dc..971f81c97 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -304,9 +304,6 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* } case MRB_TT_DATA: (*t) += mrb_objspace_page_slot_size(); - if(mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "memsize"))) { - (*t) += mrb_fixnum(mrb_funcall(mrb, obj, "memsize", 0)); - } break; #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: @@ -390,11 +387,6 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* * the final sum. It avoids infinite recursion and over counting objects by * internally tracking discovered object ids. * - * MRB_TT_DATA objects aren't calculated beyond their original page slot. However, - * if the object implements a memsize method it will call that method and add the - * return value to the total. This provides an opportunity for C based data structures - * to report their memory usage. - * */ static mrb_value -- cgit v1.2.3 From f00657ead7c3e5f6f9a346d7797a280b5c9f02fa Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 11:15:07 +0900 Subject: Remove recursive `memsize_of`; #5032 This is enhancement from CRuby's `memsize_of`. We need to change the CRuby first for the enhancement. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 134 ++++++++-------------- mrbgems/mruby-objectspace/test/objectspace.rb | 69 +---------- 2 files changed, 51 insertions(+), 152 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 971f81c97..71a7e1b8b 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -176,83 +176,66 @@ os_each_object(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(d.count); } -static void os_memsize_of_object(mrb_state*,mrb_value,mrb_value,mrb_int*); - -struct os_memsize_cb_data { - mrb_int *t; - mrb_value recurse; -}; - -static int -os_memsize_ivar_cb(mrb_state *mrb, mrb_sym _name, mrb_value obj, void *data) +static mrb_int +os_memsize_of_ivars(mrb_state* mrb, mrb_value obj) { - struct os_memsize_cb_data *cb_data = (struct os_memsize_cb_data *)(data); - os_memsize_of_object(mrb, obj, cb_data->recurse, cb_data->t); - return 0; -} - -static void -os_memsize_of_ivars(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int *t) -{ - (*t) += mrb_obj_iv_tbl_memsize(mrb, obj); - if(!mrb_nil_p(recurse)) { - struct os_memsize_cb_data cb_data = {t, recurse}; - mrb_iv_foreach(mrb, obj, os_memsize_ivar_cb, &cb_data); - } + return mrb_obj_iv_tbl_memsize(mrb, obj); } -static void -os_memsize_of_irep(mrb_state* state, struct mrb_irep *irep, mrb_int* t) +static mrb_int +os_memsize_of_irep(mrb_state* state, struct mrb_irep *irep) { - mrb_int i; - (*t) += (irep->slen * sizeof(mrb_sym)) + - (irep->plen * sizeof(mrb_code)) + - (irep->ilen * sizeof(mrb_code)); + mrb_int size, i; + size = (irep->slen * sizeof(mrb_sym)) + + (irep->plen * sizeof(mrb_code)) + + (irep->ilen * sizeof(mrb_code)); for(i = 0; i < irep->rlen; i++) { - os_memsize_of_irep(state, irep->reps[i], t); + size += os_memsize_of_irep(state, irep->reps[i]); } + return size; } -static void -os_memsize_of_method(mrb_state* mrb, mrb_value method_obj, mrb_int* t) +static mrb_int +os_memsize_of_method(mrb_state* mrb, mrb_value method_obj) { + mrb_int size; mrb_value proc_value = mrb_obj_iv_get(mrb, mrb_obj_ptr(method_obj), mrb_intern_lit(mrb, "_proc")); struct RProc *proc = mrb_proc_ptr(proc_value); - (*t) += sizeof(struct RProc); - if(!MRB_PROC_CFUNC_P(proc)) os_memsize_of_irep(mrb, proc->body.irep, t); + size = sizeof(struct RProc); + if(!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); + return size; } -static void -os_memsize_of_methods(mrb_state* mrb, mrb_value obj, mrb_int* t) +static mrb_int +os_memsize_of_methods(mrb_state* mrb, mrb_value obj) { mrb_value method_list; + mrb_int size = 0; mrb_int i; - if(!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "instance_methods"))) return; + + if(!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "instance_methods"))) return 0; method_list = mrb_funcall(mrb, obj, "instance_methods", 1, mrb_false_value()); for(i = 0; i < RARRAY_LEN(method_list); i++) { mrb_value method = mrb_funcall(mrb, obj, "instance_method", 1, mrb_ary_ref(mrb, method_list, i)); - os_memsize_of_method(mrb, method, t); + size += os_memsize_of_method(mrb, method); } + return size; } -static void -os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* t) +static mrb_int +os_memsize_of_object(mrb_state* mrb, mrb_value obj) { - if(!mrb_nil_p(recurse)) { - const mrb_value obj_id = mrb_fixnum_value(mrb_obj_id(obj)); - if(mrb_hash_key_p(mrb, recurse, obj_id)) return; - mrb_hash_set(mrb, recurse, obj_id, mrb_true_value()); - } + mrb_int size = 0; switch(obj.tt) { case MRB_TT_STRING: - (*t) += mrb_objspace_page_slot_size(); + size += mrb_objspace_page_slot_size(); if (!RSTR_EMBED_P(RSTRING(obj)) && !RSTR_SHARED_P(RSTRING(obj))) { - (*t) += RSTRING_CAPA(obj); + size += RSTRING_CAPA(obj); } break; case MRB_TT_CLASS: @@ -261,61 +244,50 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* case MRB_TT_SCLASS: case MRB_TT_ICLASS: case MRB_TT_OBJECT: { - (*t) += mrb_objspace_page_slot_size(); - os_memsize_of_ivars(mrb, obj, recurse, t); + size += mrb_objspace_page_slot_size(); + size += os_memsize_of_ivars(mrb, obj); if(mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod"))) { - os_memsize_of_method(mrb, obj, t); + size += os_memsize_of_method(mrb, obj); } else { - os_memsize_of_methods(mrb, obj, t); + size += os_memsize_of_methods(mrb, obj); } break; } case MRB_TT_HASH: { - (*t) += mrb_objspace_page_slot_size() + + size += mrb_objspace_page_slot_size() + mrb_os_memsize_of_hash_table(obj); - if(!mrb_nil_p(recurse)) { - os_memsize_of_object(mrb, mrb_hash_keys(mrb, obj), recurse, t); - os_memsize_of_object(mrb, mrb_hash_values(mrb, obj), recurse, t); - } break; } case MRB_TT_ARRAY: { - mrb_int len, i; - len = RARRAY_LEN(obj); + mrb_int len = RARRAY_LEN(obj); /* Arrays that do not fit within an RArray perform a heap allocation * storing an array of pointers to the original objects*/ - (*t) += mrb_objspace_page_slot_size(); - if(len > MRB_ARY_EMBED_LEN_MAX) (*t) += sizeof(mrb_value *) * len; - - if(!mrb_nil_p(recurse)) { - for(i = 0; i < len; i++) { - os_memsize_of_object(mrb, ARY_PTR(mrb_ary_ptr(obj))[i], recurse, t); - } - } + size += mrb_objspace_page_slot_size(); + if(len > MRB_ARY_EMBED_LEN_MAX) size += sizeof(mrb_value *) * len; break; } case MRB_TT_PROC: { struct RProc* proc = mrb_proc_ptr(obj); - (*t) += mrb_objspace_page_slot_size(); - (*t) += MRB_ENV_LEN(proc->e.env) * sizeof(mrb_value); - if(!MRB_PROC_CFUNC_P(proc)) os_memsize_of_irep(mrb, proc->body.irep, t); + size += mrb_objspace_page_slot_size(); + size += MRB_ENV_LEN(proc->e.env) * sizeof(mrb_value); + if(!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); break; } case MRB_TT_DATA: - (*t) += mrb_objspace_page_slot_size(); + size += mrb_objspace_page_slot_size(); break; #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: #ifdef MRB_WORD_BOXING - (*t) += mrb_objspace_page_slot_size() + + size += mrb_objspace_page_slot_size() + sizeof(struct RFloat); #endif break; #endif case MRB_TT_RANGE: #ifndef MRB_RANGE_EMBED - (*t) += mrb_objspace_page_slot_size() + + size += mrb_objspace_page_slot_size() + sizeof(struct mrb_range_edges); #endif break; @@ -327,17 +299,17 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* mrb_int i = 0; while(ci_p < f->cxt->ciend) { - if(ci_p->proc) os_memsize_of_irep(mrb, ci_p->proc->body.irep, t); + if(ci_p->proc) size += os_memsize_of_irep(mrb, ci_p->proc->body.irep); ci_p++; } if(f->cxt->esize) { for(i = 0; i <= f->cxt->esize; i++) { - os_memsize_of_irep(mrb, f->cxt->ensure[i]->body.irep, t); + size += os_memsize_of_irep(mrb, f->cxt->ensure[i]->body.irep); } } - (*t) += mrb_objspace_page_slot_size() + + size += mrb_objspace_page_slot_size() + sizeof(struct RFiber) + sizeof(struct mrb_context) + sizeof(struct RProc *) * f->cxt->esize + @@ -347,7 +319,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* break; } case MRB_TT_ISTRUCT: - (*t) += mrb_objspace_page_slot_size(); + size += mrb_objspace_page_slot_size(); break; /* zero heap size types. * immediate VM stack values, contained within mrb_state, or on C stack */ @@ -366,6 +338,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* case MRB_TT_MAXDEFINE: break; } + return size; } /* @@ -394,17 +367,10 @@ os_memsize_of(mrb_state *mrb, mrb_value self) { mrb_int total; mrb_value obj; - mrb_value recurse; - const char *kw_names[1] = { "recurse" }; - mrb_value kw_values[1]; - const mrb_kwargs kwargs = { 1, kw_values, kw_names, 0, NULL }; - - mrb_get_args(mrb, "o:", &obj, &kwargs); - recurse = (!mrb_undef_p(kw_values[0]) && mrb_test(kw_values[0]))? mrb_hash_new(mrb) : mrb_nil_value(); - total = 0; - os_memsize_of_object(mrb, obj, recurse, &total); + mrb_get_args(mrb, "o", &obj); + total = os_memsize_of_object(mrb, obj); return mrb_fixnum_value(total); } diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb index 610cdfbfa..c8f0c4d24 100644 --- a/mrbgems/mruby-objectspace/test/objectspace.rb +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -1,4 +1,4 @@ -# coding: utf-8 +# coding: cp932 assert('ObjectSpace.count_objects') do h = {} f = Fiber.new {} if Object.const_defined?(:Fiber) @@ -134,71 +134,4 @@ assert 'ObjectSpace.memsize_of' do #hash assert_not_equal ObjectSpace.memsize_of({}), 0, 'empty hash size not zero' - - # recursion - foo_str = 'foo' * 10 - bar_str = 'bar' * 10 - caz_str = 'caz' * 10 - fbc_ary = [foo_str, bar_str, caz_str] - assert_operator ObjectSpace.memsize_of(fbc_ary), - :<, - ObjectSpace.memsize_of(fbc_ary, recurse: true), - 'basic array recursion' - - big_ary = [ 'a' * 10, - [ 'b' * 10, - [ 'c' * 10, - [ 'd' * 10, - [ 'e' * 10, - [ 'f' * 10, - ['g' * 10] - ] * 10, - ] * 10, - ] * 10, - ] * 10, - ] * 10, - ] * 10 - assert_operator ObjectSpace.memsize_of(big_ary), - :<, - ObjectSpace.memsize_of(big_ary, recurse: true), - 'large array recursion' - - assert_nothing_raised 'infinite array recursion' do - ObjectSpace.memsize_of(fbc_ary.push(fbc_ary)) - end - - basic_hsh = {a: [foo_str, bar_str], b: caz_str, 'c' => {}} - assert_operator ObjectSpace.memsize_of(basic_hsh), - :<, - ObjectSpace.memsize_of(basic_hsh, recurse: true), - 'hash recursion with basic keys' - - weird_keys = {big_ary => foo_str} - assert_operator ObjectSpace.memsize_of(weird_keys), - :<, - ObjectSpace.memsize_of(weird_keys, recurse: true), - 'hash recursion with collection as key' - - basic_hsh.store('d', basic_hsh) - assert_nothing_raised 'hash value recursion' do - ObjectSpace.memsize_of basic_hsh, recurse: true - end - - foo_klass = Class.new do - def bar= b - @bar = b - end - end - - fk_one = foo_klass.new - fk_one.bar = fbc_ary - assert_operator ObjectSpace.memsize_of(fk_one), - :<, - ObjectSpace.memsize_of(fk_one, recurse: true), - 'basic ivar recursion' - - fk_one.bar = fk_one - assert_nothing_raised 'ivar infinite recursion' do - ObjectSpace.memsize_of(fk_one, recurse: true) - end end -- cgit v1.2.3 From a2b8c08a52867190ea90ba8076a296b368470200 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 09:42:17 +0900 Subject: Add `const` to `irep` pointer in `os_memsize_of_irep`; #5032 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 71a7e1b8b..6ac1ab51b 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -183,7 +183,7 @@ os_memsize_of_ivars(mrb_state* mrb, mrb_value obj) } static mrb_int -os_memsize_of_irep(mrb_state* state, struct mrb_irep *irep) +os_memsize_of_irep(mrb_state* state, const struct mrb_irep *irep) { mrb_int size, i; size = (irep->slen * sizeof(mrb_sym)) + -- cgit v1.2.3 From 9f52bcfca9c23cba27f0ff50dacb1704057e1042 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 11:50:12 +0900 Subject: Fix `memsize_of` Fibers; #5032 Memory size of a Fiber is calculated by stack size only in CRuby. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 13 ------------- mrbgems/mruby-objectspace/test/objectspace.rb | 1 - 2 files changed, 14 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 6ac1ab51b..9ad7ee619 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -293,21 +293,8 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj) break; case MRB_TT_FIBER: { struct RFiber* f = (struct RFiber *)mrb_ptr(obj); - mrb_callinfo *ci_p = f->cxt->cibase; ptrdiff_t stack_size = f->cxt->stend - f->cxt->stbase; ptrdiff_t ci_size = f->cxt->ciend - f->cxt->cibase; - mrb_int i = 0; - - while(ci_p < f->cxt->ciend) { - if(ci_p->proc) size += os_memsize_of_irep(mrb, ci_p->proc->body.irep); - ci_p++; - } - - if(f->cxt->esize) { - for(i = 0; i <= f->cxt->esize; i++) { - size += os_memsize_of_irep(mrb, f->cxt->ensure[i]->body.irep); - } - } size += mrb_objspace_page_slot_size() + sizeof(struct RFiber) + diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb index c8f0c4d24..d029a2f43 100644 --- a/mrbgems/mruby-objectspace/test/objectspace.rb +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -130,7 +130,6 @@ assert 'ObjectSpace.memsize_of' do # fiber empty_fiber_size = ObjectSpace.memsize_of(Fiber.new {}) assert_not_equal empty_fiber_size, 0, 'empty fiber not zero' - assert_operator empty_fiber_size, :<, ObjectSpace.memsize_of(Fiber.new { yield; 1 }), 'Fiber code size growth' #hash assert_not_equal ObjectSpace.memsize_of({}), 0, 'empty hash size not zero' -- cgit v1.2.3 From 495c1a377a63f0f56916c478f616eeb667bb3811 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 12:31:00 +0900 Subject: Fix `memsize_of` to count method table size; #5032 Also avoid `mrb_funcall` to minimize VM recursion. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 29 +++++------------------ 1 file changed, 6 insertions(+), 23 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 9ad7ee619..d46c5c2d1 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -205,24 +205,7 @@ os_memsize_of_method(mrb_state* mrb, mrb_value method_obj) struct RProc *proc = mrb_proc_ptr(proc_value); size = sizeof(struct RProc); - if(!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); - return size; -} - -static mrb_int -os_memsize_of_methods(mrb_state* mrb, mrb_value obj) -{ - mrb_value method_list; - mrb_int size = 0; - mrb_int i; - - if(!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "instance_methods"))) return 0; - method_list = mrb_funcall(mrb, obj, "instance_methods", 1, mrb_false_value()); - for(i = 0; i < RARRAY_LEN(method_list); i++) { - mrb_value method = mrb_funcall(mrb, obj, "instance_method", 1, - mrb_ary_ref(mrb, method_list, i)); - size += os_memsize_of_method(mrb, method); - } + if (!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); return size; } @@ -240,18 +223,18 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj) break; case MRB_TT_CLASS: case MRB_TT_MODULE: - case MRB_TT_EXCEPTION: case MRB_TT_SCLASS: case MRB_TT_ICLASS: + size += mrb_gc_mark_mt_size(mrb, mrb_class_ptr(obj)) * sizeof(mrb_method_t); + /* fall through */ + case MRB_TT_EXCEPTION: case MRB_TT_OBJECT: { size += mrb_objspace_page_slot_size(); size += os_memsize_of_ivars(mrb, obj); - if(mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod"))) { + if (mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod")) || + mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "Method"))){ size += os_memsize_of_method(mrb, obj); } - else { - size += os_memsize_of_methods(mrb, obj); - } break; } case MRB_TT_HASH: { -- cgit v1.2.3 From e41f1f5139ef03dac2bd1c0b9a7a4143ddf07f59 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 12:32:54 +0900 Subject: Fix indent of compiler conditions; #5032 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index d46c5c2d1..9ac75c710 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -260,19 +260,19 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj) case MRB_TT_DATA: size += mrb_objspace_page_slot_size(); break; - #ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: - #ifdef MRB_WORD_BOXING +#ifdef MRB_WORD_BOXING size += mrb_objspace_page_slot_size() + sizeof(struct RFloat); - #endif +#endif break; - #endif +#endif case MRB_TT_RANGE: - #ifndef MRB_RANGE_EMBED +#ifndef MRB_RANGE_EMBED size += mrb_objspace_page_slot_size() + sizeof(struct mrb_range_edges); - #endif +#endif break; case MRB_TT_FIBER: { struct RFiber* f = (struct RFiber *)mrb_ptr(obj); -- cgit v1.2.3 From fe1ec9afdd1dbfd579efe5c9823f554e26d75a2d Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Fri, 17 Jul 2020 20:09:44 -0700 Subject: Add ObjectSpace.memsize_of_all --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 25 +++++++++++++++++++++++ mrbgems/mruby-objectspace/test/objectspace.rb | 15 +++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 9ac75c710..6da2a4104 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -344,6 +344,30 @@ os_memsize_of(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(total); } +struct os_memsize_of_all_cb_data { + mrb_int t; + struct RClass *type; +}; + +static int +os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) +{ + struct os_memsize_of_all_cb_data *data = (struct os_memsize_of_all_cb_data *)d; + if(obj->c == data->type) data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); + return 0; +} + +static mrb_value +os_memsize_of_all(mrb_state *mrb, mrb_value self) +{ + mrb_value type; + struct os_memsize_of_all_cb_data data = { 0 }; + mrb_get_args(mrb, "C", &type); + data.type = mrb_class_ptr(type); + mrb_objspace_each_objects(mrb, os_memsize_of_all_cb, &data); + return mrb_fixnum_value(data.t); +} + void mrb_mruby_objectspace_gem_init(mrb_state *mrb) { @@ -351,6 +375,7 @@ mrb_mruby_objectspace_gem_init(mrb_state *mrb) mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_OPT(1)); mrb_define_class_method(mrb, os, "each_object", os_each_object, MRB_ARGS_OPT(1)); mrb_define_class_method(mrb, os, "memsize_of", os_memsize_of, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); + mrb_define_class_method(mrb, os, "memsize_of_all", os_memsize_of_all, MRB_ARGS_REQ(1)); } void diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb index d029a2f43..e5783b942 100644 --- a/mrbgems/mruby-objectspace/test/objectspace.rb +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -1,4 +1,3 @@ -# coding: cp932 assert('ObjectSpace.count_objects') do h = {} f = Fiber.new {} if Object.const_defined?(:Fiber) @@ -134,3 +133,17 @@ assert 'ObjectSpace.memsize_of' do #hash assert_not_equal ObjectSpace.memsize_of({}), 0, 'empty hash size not zero' end + +assert 'ObjectSpace.memsize_of_all' do + foo_class = Class.new do + def initialize + @a = 'a' + @b = 'b' + end + end + + foos = Array.new(10) { foo_class.new } + foo_size = ObjectSpace.memsize_of(foos.first) + + assert_equal ObjectSpace.memsize_of_all(foo_class), foo_size * foos.size, 'Memsize of all instance' +end -- cgit v1.2.3 From a79d1ba9ffe4d3c2c092f118c68ca8a0e311af0b Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Fri, 17 Jul 2020 20:21:23 -0700 Subject: Adding memsize_of_all doc --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 6da2a4104..f5cc7b753 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -357,6 +357,14 @@ os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) return 0; } +/* + * call-seq: + * ObjectSpace.memsize_of_all([klass]) -> Numeric + * + * Return consuming memory size of all living objects of type klass. + * + */ + static mrb_value os_memsize_of_all(mrb_state *mrb, mrb_value self) { -- cgit v1.2.3 From ffe8bf6323a6fd9a0b68b3e84745ccc820b2bc49 Mon Sep 17 00:00:00 2001 From: Rory O'Connell <19547+RoryO@users.noreply.github.com> Date: Sat, 18 Jul 2020 13:55:45 -0700 Subject: Avoid singleton classes with mrb_class_real --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index f5cc7b753..b3e8605d7 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -353,7 +353,7 @@ static int os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) { struct os_memsize_of_all_cb_data *data = (struct os_memsize_of_all_cb_data *)d; - if(obj->c == data->type) data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); + if(mrb_class_real(obj->c) == data->type) data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); return 0; } -- cgit v1.2.3 From 6d073f8d99f6b4cbc1549f02298a785aba9b9a7a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 06:57:34 +0900 Subject: Fix `memsize_of_all` to count memory of subclass instances; #5040 `ObjectSpace.memsize_of_all` takes a class and count memory size of all instances of the class and its subclasses (if any). --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index b3e8605d7..6ae030dff 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -353,7 +353,8 @@ static int os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) { struct os_memsize_of_all_cb_data *data = (struct os_memsize_of_all_cb_data *)d; - if(mrb_class_real(obj->c) == data->type) data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); + if(mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), data->type)) + data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); return 0; } -- cgit v1.2.3 From 5b2763821e1be3709fd70d732ad1ed6c343f649f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 07:42:35 +0900 Subject: Fix `memsize_of_all` to count all objects if no argument given; #5040 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 6ae030dff..b02e01919 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -353,7 +353,17 @@ static int os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) { struct os_memsize_of_all_cb_data *data = (struct os_memsize_of_all_cb_data *)d; - if(mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), data->type)) + switch (obj->tt) { + case MRB_TT_FREE: case MRB_TT_ENV: + case MRB_TT_BREAK: case MRB_TT_ICLASS: + /* internal objects that should not be counted */ + return 0; + default: + break; + } + /* skip Proc objects for methods */ + if (obj->c == NULL) return 0; + if (data->type == NULL || mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), data->type)) data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); return 0; } @@ -369,9 +379,9 @@ os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) static mrb_value os_memsize_of_all(mrb_state *mrb, mrb_value self) { - mrb_value type; + mrb_value type = mrb_nil_value(); struct os_memsize_of_all_cb_data data = { 0 }; - mrb_get_args(mrb, "C", &type); + mrb_get_args(mrb, "|C", &type); data.type = mrb_class_ptr(type); mrb_objspace_each_objects(mrb, os_memsize_of_all_cb, &data); return mrb_fixnum_value(data.t); -- cgit v1.2.3 From f76defd310c03ace8750abec22938ed3427fceee Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 07:47:07 +0900 Subject: Use `c` specifier for `mrb_get_args`. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 12 +++--------- src/class.c | 12 ++++++------ src/kernel.c | 12 ++++++------ 3 files changed, 15 insertions(+), 21 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index b02e01919..16c520732 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -166,12 +166,8 @@ os_each_object_cb(mrb_state *mrb, struct RBasic *obj, void *ud) static mrb_value os_each_object(mrb_state *mrb, mrb_value self) { - mrb_value cls = mrb_nil_value(); - struct os_each_object_data d; - mrb_get_args(mrb, "&!|C", &d.block, &cls); - - d.target_module = mrb_nil_p(cls) ? NULL : mrb_class_ptr(cls); - d.count = 0; + struct os_each_object_data d = {0}; + mrb_get_args(mrb, "&!|c", &d.block, &d.target_module); mrb_objspace_each_objects(mrb, os_each_object_cb, &d); return mrb_fixnum_value(d.count); } @@ -379,10 +375,8 @@ os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) static mrb_value os_memsize_of_all(mrb_state *mrb, mrb_value self) { - mrb_value type = mrb_nil_value(); struct os_memsize_of_all_cb_data data = { 0 }; - mrb_get_args(mrb, "|C", &type); - data.type = mrb_class_ptr(type); + mrb_get_args(mrb, "|c", &data.type); mrb_objspace_each_objects(mrb, os_memsize_of_all_cb, &data); return mrb_fixnum_value(data.t); } diff --git a/src/class.c b/src/class.c index 30dc4c17a..fc8a38ff9 100644 --- a/src/class.c +++ b/src/class.c @@ -1168,22 +1168,22 @@ mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) static mrb_value mrb_mod_prepend_features(mrb_state *mrb, mrb_value mod) { - mrb_value klass; + struct RClass *c; mrb_check_type(mrb, mod, MRB_TT_MODULE); - mrb_get_args(mrb, "C", &klass); - mrb_prepend_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod)); + mrb_get_args(mrb, "c", &c); + mrb_prepend_module(mrb, c, mrb_class_ptr(mod)); return mod; } static mrb_value mrb_mod_append_features(mrb_state *mrb, mrb_value mod) { - mrb_value klass; + struct RClass *c; mrb_check_type(mrb, mod, MRB_TT_MODULE); - mrb_get_args(mrb, "C", &klass); - mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod)); + mrb_get_args(mrb, "c", &c); + mrb_include_module(mrb, c, mrb_class_ptr(mod)); return mod; } diff --git a/src/kernel.c b/src/kernel.c index a74f8a8ed..682feb13c 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -520,11 +520,11 @@ mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c) static mrb_value obj_is_instance_of(mrb_state *mrb, mrb_value self) { - mrb_value arg; + struct RClass *c; - mrb_get_args(mrb, "C", &arg); + mrb_get_args(mrb, "c", &c); - return mrb_bool_value(mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg))); + return mrb_bool_value(mrb_obj_is_instance_of(mrb, self, c)); } /* 15.3.1.3.24 */ @@ -557,11 +557,11 @@ obj_is_instance_of(mrb_state *mrb, mrb_value self) static mrb_value mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self) { - mrb_value arg; + struct RClass *c; - mrb_get_args(mrb, "C", &arg); + mrb_get_args(mrb, "c", &c); - return mrb_bool_value(mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg))); + return mrb_bool_value(mrb_obj_is_kind_of(mrb, self, c)); } KHASH_DECLARE(st, mrb_sym, char, FALSE) -- cgit v1.2.3 From 00337543a5baf0e2cbedd65a697710a557b72041 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 09:11:16 +0900 Subject: Should have updated the arg spec for `memsize_of`&`memsize_of_all`; #5040 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 16c520732..d8ce19e82 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -387,8 +387,8 @@ mrb_mruby_objectspace_gem_init(mrb_state *mrb) struct RClass *os = mrb_define_module(mrb, "ObjectSpace"); mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_OPT(1)); mrb_define_class_method(mrb, os, "each_object", os_each_object, MRB_ARGS_OPT(1)); - mrb_define_class_method(mrb, os, "memsize_of", os_memsize_of, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); - mrb_define_class_method(mrb, os, "memsize_of_all", os_memsize_of_all, MRB_ARGS_REQ(1)); + mrb_define_class_method(mrb, os, "memsize_of", os_memsize_of, MRB_ARGS_REQ(1)); + mrb_define_class_method(mrb, os, "memsize_of_all", os_memsize_of_all, MRB_ARGS_OPT(1)); } void -- cgit v1.2.3 From 1d2c5c12d373751835097d95e34924a005334cd2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 13:10:08 +0900 Subject: Reorder members of `struct os_each_object_data` to stop warnings. `mrb_value` may or may not be struct according to configuration. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index d8ce19e82..1b293f019 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -112,9 +112,9 @@ os_count_objects(mrb_state *mrb, mrb_value self) } struct os_each_object_data { - mrb_value block; struct RClass *target_module; mrb_int count; + mrb_value block; }; static int -- cgit v1.2.3 From 71254be076eb25b77840276c910f1b6f43c3bd17 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 13:11:53 +0900 Subject: Skip `MRB_TT_FREE` and `MRB_TT_BREAK` in `each_object`. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 1b293f019..5febe6e3e 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -129,8 +129,8 @@ os_each_object_cb(mrb_state *mrb, struct RBasic *obj, void *ud) /* filter internal objects */ switch (obj->tt) { - case MRB_TT_ENV: - case MRB_TT_ICLASS: + case MRB_TT_FREE: case MRB_TT_ENV: + case MRB_TT_BREAK: case MRB_TT_ICLASS: return MRB_EACH_OBJ_OK; default: break; -- cgit v1.2.3 From 07b75d927e1e97ad4fe3dd2288ea07343b9a84ee Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 13:15:01 +0900 Subject: Replace 0 by `MRB_EACH_OBJ_OK`; #5040 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 5febe6e3e..4a3b38cee 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -353,7 +353,7 @@ os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) case MRB_TT_FREE: case MRB_TT_ENV: case MRB_TT_BREAK: case MRB_TT_ICLASS: /* internal objects that should not be counted */ - return 0; + return MRB_EACH_OBJ_OK; default: break; } @@ -361,7 +361,7 @@ os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) if (obj->c == NULL) return 0; if (data->type == NULL || mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), data->type)) data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); - return 0; + return MRB_EACH_OBJ_OK; } /* -- cgit v1.2.3 From a6f31ad6ce29ab07a2f96f678f66e7923f765642 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 22:41:09 +0900 Subject: Avoid accessing `obj.tt` of `mrb_value`; #5040 The old code compiles only on `MRB_NO_BOXING`. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 4a3b38cee..6804a99ae 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -210,7 +210,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj) { mrb_int size = 0; - switch(obj.tt) { + switch(mrb_type(obj)) { case MRB_TT_STRING: size += mrb_objspace_page_slot_size(); if (!RSTR_EMBED_P(RSTRING(obj)) && !RSTR_SHARED_P(RSTRING(obj))) { -- cgit v1.2.3 From 639703cf018f54a5962a19fc8df5bcfa48308238 Mon Sep 17 00:00:00 2001 From: dearblue Date: Tue, 21 Jul 2020 23:32:30 +0900 Subject: Remove unnecessory methods in `mruby-objectspace`; ref #5041 The `ObjectSpace#memsize_of` and `ObjectSpace#memsize_of_all` in `mruby-objectspace` ware migrated to `mruby-os-memsize` mrbgem. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 211 ---------------------- 1 file changed, 211 deletions(-) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 6804a99ae..408d3c0af 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -172,223 +172,12 @@ os_each_object(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(d.count); } -static mrb_int -os_memsize_of_ivars(mrb_state* mrb, mrb_value obj) -{ - return mrb_obj_iv_tbl_memsize(mrb, obj); -} - -static mrb_int -os_memsize_of_irep(mrb_state* state, const struct mrb_irep *irep) -{ - mrb_int size, i; - size = (irep->slen * sizeof(mrb_sym)) + - (irep->plen * sizeof(mrb_code)) + - (irep->ilen * sizeof(mrb_code)); - - for(i = 0; i < irep->rlen; i++) { - size += os_memsize_of_irep(state, irep->reps[i]); - } - return size; -} - -static mrb_int -os_memsize_of_method(mrb_state* mrb, mrb_value method_obj) -{ - mrb_int size; - mrb_value proc_value = mrb_obj_iv_get(mrb, mrb_obj_ptr(method_obj), - mrb_intern_lit(mrb, "_proc")); - struct RProc *proc = mrb_proc_ptr(proc_value); - - size = sizeof(struct RProc); - if (!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); - return size; -} - -static mrb_int -os_memsize_of_object(mrb_state* mrb, mrb_value obj) -{ - mrb_int size = 0; - - switch(mrb_type(obj)) { - case MRB_TT_STRING: - size += mrb_objspace_page_slot_size(); - if (!RSTR_EMBED_P(RSTRING(obj)) && !RSTR_SHARED_P(RSTRING(obj))) { - size += RSTRING_CAPA(obj); - } - break; - case MRB_TT_CLASS: - case MRB_TT_MODULE: - case MRB_TT_SCLASS: - case MRB_TT_ICLASS: - size += mrb_gc_mark_mt_size(mrb, mrb_class_ptr(obj)) * sizeof(mrb_method_t); - /* fall through */ - case MRB_TT_EXCEPTION: - case MRB_TT_OBJECT: { - size += mrb_objspace_page_slot_size(); - size += os_memsize_of_ivars(mrb, obj); - if (mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod")) || - mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "Method"))){ - size += os_memsize_of_method(mrb, obj); - } - break; - } - case MRB_TT_HASH: { - size += mrb_objspace_page_slot_size() + - mrb_os_memsize_of_hash_table(obj); - break; - } - case MRB_TT_ARRAY: { - mrb_int len = RARRAY_LEN(obj); - /* Arrays that do not fit within an RArray perform a heap allocation - * storing an array of pointers to the original objects*/ - size += mrb_objspace_page_slot_size(); - if(len > MRB_ARY_EMBED_LEN_MAX) size += sizeof(mrb_value *) * len; - break; - } - case MRB_TT_PROC: { - struct RProc* proc = mrb_proc_ptr(obj); - size += mrb_objspace_page_slot_size(); - size += MRB_ENV_LEN(proc->e.env) * sizeof(mrb_value); - if(!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); - break; - } - case MRB_TT_DATA: - size += mrb_objspace_page_slot_size(); - break; -#ifndef MRB_WITHOUT_FLOAT - case MRB_TT_FLOAT: -#ifdef MRB_WORD_BOXING - size += mrb_objspace_page_slot_size() + - sizeof(struct RFloat); -#endif - break; -#endif - case MRB_TT_RANGE: -#ifndef MRB_RANGE_EMBED - size += mrb_objspace_page_slot_size() + - sizeof(struct mrb_range_edges); -#endif - break; - case MRB_TT_FIBER: { - struct RFiber* f = (struct RFiber *)mrb_ptr(obj); - ptrdiff_t stack_size = f->cxt->stend - f->cxt->stbase; - ptrdiff_t ci_size = f->cxt->ciend - f->cxt->cibase; - - size += mrb_objspace_page_slot_size() + - sizeof(struct RFiber) + - sizeof(struct mrb_context) + - sizeof(struct RProc *) * f->cxt->esize + - sizeof(uint16_t *) * f->cxt->rsize + - sizeof(mrb_value) * stack_size + - sizeof(mrb_callinfo) * ci_size; - break; - } - case MRB_TT_ISTRUCT: - size += mrb_objspace_page_slot_size(); - break; - /* zero heap size types. - * immediate VM stack values, contained within mrb_state, or on C stack */ - case MRB_TT_TRUE: - case MRB_TT_FALSE: - case MRB_TT_FIXNUM: - case MRB_TT_BREAK: - case MRB_TT_CPTR: - case MRB_TT_SYMBOL: - case MRB_TT_FREE: - case MRB_TT_UNDEF: - case MRB_TT_ENV: - /* never used, silences compiler warning - * not having a default: clause lets the compiler tell us when there is a new - * TT not accounted for */ - case MRB_TT_MAXDEFINE: - break; - } - return size; -} - -/* - * call-seq: - * ObjectSpace.memsize_of(obj, recurse: false) -> Numeric - * - * Returns the amount of heap memory allocated for object in size_t units. - * - * The return value depends on the definition of size_t on that platform, - * therefore the value is not comparable across platform types. - * - * Immediate values such as integers, booleans, symbols and unboxed float numbers - * return 0. Additionally special objects which are small enough to fit inside an - * object pointer, termed embedded objects, will return the size of the object pointer. - * Strings and arrays below a compile-time defined size may be embedded. - * - * Setting recurse: true descends into instance variables, array members, - * hash keys and hash values recursively, calculating the child objects and adding to - * the final sum. It avoids infinite recursion and over counting objects by - * internally tracking discovered object ids. - * - */ - -static mrb_value -os_memsize_of(mrb_state *mrb, mrb_value self) -{ - mrb_int total; - mrb_value obj; - - mrb_get_args(mrb, "o", &obj); - - total = os_memsize_of_object(mrb, obj); - return mrb_fixnum_value(total); -} - -struct os_memsize_of_all_cb_data { - mrb_int t; - struct RClass *type; -}; - -static int -os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) -{ - struct os_memsize_of_all_cb_data *data = (struct os_memsize_of_all_cb_data *)d; - switch (obj->tt) { - case MRB_TT_FREE: case MRB_TT_ENV: - case MRB_TT_BREAK: case MRB_TT_ICLASS: - /* internal objects that should not be counted */ - return MRB_EACH_OBJ_OK; - default: - break; - } - /* skip Proc objects for methods */ - if (obj->c == NULL) return 0; - if (data->type == NULL || mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), data->type)) - data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); - return MRB_EACH_OBJ_OK; -} - -/* - * call-seq: - * ObjectSpace.memsize_of_all([klass]) -> Numeric - * - * Return consuming memory size of all living objects of type klass. - * - */ - -static mrb_value -os_memsize_of_all(mrb_state *mrb, mrb_value self) -{ - struct os_memsize_of_all_cb_data data = { 0 }; - mrb_get_args(mrb, "|c", &data.type); - mrb_objspace_each_objects(mrb, os_memsize_of_all_cb, &data); - return mrb_fixnum_value(data.t); -} - void mrb_mruby_objectspace_gem_init(mrb_state *mrb) { struct RClass *os = mrb_define_module(mrb, "ObjectSpace"); mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_OPT(1)); mrb_define_class_method(mrb, os, "each_object", os_each_object, MRB_ARGS_OPT(1)); - mrb_define_class_method(mrb, os, "memsize_of", os_memsize_of, MRB_ARGS_REQ(1)); - mrb_define_class_method(mrb, os, "memsize_of_all", os_memsize_of_all, MRB_ARGS_OPT(1)); } void -- cgit v1.2.3 From b4f4f5968b7c5e05b91bf7a62a0438b0d4c9133e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 23 Jul 2020 07:10:35 +0900 Subject: `ObjectSpace.count_objects` to support `MRB_TT_ISTRUCT`; #5046 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 1 + 1 file changed, 1 insertion(+) (limited to 'mrbgems/mruby-objectspace/src/mruby_objectspace.c') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 6804a99ae..de5a4f025 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -100,6 +100,7 @@ os_count_objects(mrb_state *mrb, mrb_value self) COUNT_TYPE(T_ENV); COUNT_TYPE(T_DATA); COUNT_TYPE(T_FIBER); + COUNT_TYPE(T_ISTRUCT); #undef COUNT_TYPE default: type = mrb_fixnum_value(i); break; -- cgit v1.2.3