diff options
author | tmm1 <tmm1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-12-05 07:45:13 +0000 |
---|---|---|
committer | tmm1 <tmm1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-12-05 07:45:13 +0000 |
commit | 241c1a5459d986187ec42f166535d51b37202532 (patch) | |
tree | 27e697e24d024fab3242323d01e8644ee164e61d /gc.c | |
parent | 97ac1f6767745e97b136f9f0e1afd56903723f1a (diff) | |
download | ruby-241c1a5459d986187ec42f166535d51b37202532.tar.gz |
gc.c: expose GC.stat() to C-api via rb_gc_stat()
* include/ruby/intern.h: add rb_gc_stat() for access to GC.stat
variables from c-api
* gc.c (rb_gc_stat): new c-api method. accepts either VALUE hash like
GC.stat, or VALUE symbol key and returns size_t directly. the second
form is useful to avoid allocations, i.e. for usage inside
INTERNAL_EVENT_GC tracepoints.
* gc.c (gc_stat): add GC.stat(:key) to return single value instead of hash
* gc.c (gc_stat_internal): helper method to retrieve single or all stat values
* test/ruby/test_gc.rb (class TestGc): test for new behavior
* NEWS: note about this new api
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44005 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 157 |
1 files changed, 101 insertions, 56 deletions
@@ -5056,49 +5056,9 @@ gc_count(VALUE self) return SIZET2NUM(rb_gc_count()); } -/* - * call-seq: - * GC.stat -> Hash - * - * Returns a Hash containing information about the GC. - * - * The hash includes information about internal statistics about GC such as: - * - * { - * :count=>2, - * :heap_used=>9, - * :heap_length=>11, - * :heap_increment=>2, - * :heap_live_slot=>6836, - * :heap_free_slot=>519, - * :heap_final_slot=>0, - * :heap_swept_slot=>818, - * :total_allocated_object=>7674, - * :total_freed_object=>838, - * :malloc_increase=>181034, - * :malloc_limit=>16777216, - * :minor_gc_count=>2, - * :major_gc_count=>0, - * :remembered_shady_object=>55, - * :remembered_shady_object_limit=>0, - * :old_object=>2422, - * :old_object_limit=>0, - * :oldmalloc_increase=>277386, - * :oldmalloc_limit=>16777216 - * } - * - * The contents of the hash are implementation specific and may be changed in - * the future. - * - * This method is only expected to work on C Ruby. - * - */ - static VALUE -gc_stat(int argc, VALUE *argv, VALUE self) +gc_stat_internal(VALUE hash_or_sym, size_t *out) { - rb_objspace_t *objspace = &rb_objspace; - VALUE hash; static VALUE sym_count; static VALUE sym_heap_used, sym_heap_length, sym_heap_increment; static VALUE sym_heap_live_slot, sym_heap_free_slot, sym_heap_final_slot, sym_heap_swept_slot; @@ -5120,6 +5080,16 @@ gc_stat(int argc, VALUE *argv, VALUE self) #endif /* RGENGC_PROFILE */ #endif /* USE_RGENGC */ + rb_objspace_t *objspace = &rb_objspace; + VALUE hash = Qnil, key = Qnil; + + if (RB_TYPE_P(hash_or_sym, T_HASH)) + hash = hash_or_sym; + else if (SYMBOL_P(hash_or_sym) && out) + key = hash_or_sym; + else + rb_raise(rb_eArgError, "non-hash or symbol argument"); + if (sym_count == 0) { #define S(s) sym_##s = ID2SYM(rb_intern_const(#s)) S(count); @@ -5161,17 +5131,12 @@ gc_stat(int argc, VALUE *argv, VALUE self) #undef S } - if (rb_scan_args(argc, argv, "01", &hash) == 1) { - if (!RB_TYPE_P(hash, T_HASH)) { - rb_raise(rb_eTypeError, "non-hash given"); - } - } - - if (hash == Qnil) { - hash = rb_hash_new(); - } +#define SET(name, attr) \ + if (key == sym_##name) \ + return (*out = attr, Qnil); \ + else if (hash != Qnil) \ + rb_hash_aset(hash, sym_##name, SIZET2NUM(attr)); -#define SET(name, attr) rb_hash_aset(hash, sym_##name, SIZET2NUM(attr)) SET(count, objspace->profile.count); /* implementation dependent counters */ @@ -5211,8 +5176,15 @@ gc_stat(int argc, VALUE *argv, VALUE self) #endif SET(remembered_normal_object_count, objspace->profile.remembered_normal_object_count); SET(remembered_shady_object_count, objspace->profile.remembered_shady_object_count); -#if RGENGC_PROFILE >= 2 - { +#endif /* RGENGC_PROFILE */ +#endif /* USE_RGENGC */ +#undef SET + + if (key != Qnil) /* matched key should return above */ + rb_raise(rb_eArgError, "unknown key: %s", RSTRING_PTR(rb_id2str(SYM2ID(key)))); + +#if defined(RGENGC_PROFILE) && RGENGC_PROFILE >= 2 + if (hash != Qnil) { gc_count_add_each_types(hash, "generated_normal_object_count_types", objspace->profile.generated_normal_object_count_types); gc_count_add_each_types(hash, "generated_shady_object_count_types", objspace->profile.generated_shady_object_count_types); gc_count_add_each_types(hash, "shade_operation_count_types", objspace->profile.shade_operation_count_types); @@ -5224,14 +5196,87 @@ gc_stat(int argc, VALUE *argv, VALUE self) gc_count_add_each_types(hash, "remembered_shady_object_count_types", objspace->profile.remembered_shady_object_count_types); } #endif -#endif /* RGENGC_PROFILE */ -#endif /* USE_RGENGC */ -#undef SET + return hash; } /* * call-seq: + * GC.stat -> Hash + * GC.stat(hash) -> hash + * GC.stat(:key) -> Numeric + * + * Returns a Hash containing information about the GC. + * + * The hash includes information about internal statistics about GC such as: + * + * { + * :count=>2, + * :heap_used=>9, + * :heap_length=>11, + * :heap_increment=>2, + * :heap_live_slot=>6836, + * :heap_free_slot=>519, + * :heap_final_slot=>0, + * :heap_swept_slot=>818, + * :total_allocated_object=>7674, + * :total_freed_object=>838, + * :malloc_increase=>181034, + * :malloc_limit=>16777216, + * :minor_gc_count=>2, + * :major_gc_count=>0, + * :remembered_shady_object=>55, + * :remembered_shady_object_limit=>0, + * :old_object=>2422, + * :old_object_limit=>0, + * :oldmalloc_increase=>277386, + * :oldmalloc_limit=>16777216 + * } + * + * The contents of the hash are implementation specific and may be changed in + * the future. + * + * This method is only expected to work on C Ruby. + * + */ + +static VALUE +gc_stat(int argc, VALUE *argv, VALUE self) +{ + VALUE arg = Qnil; + + if (rb_scan_args(argc, argv, "01", &arg) == 1) { + if (SYMBOL_P(arg)) { + size_t value = 0; + gc_stat_internal(arg, &value); + return SIZET2NUM(value); + } else if (!RB_TYPE_P(arg, T_HASH)) { + rb_raise(rb_eTypeError, "non-hash given"); + } + } + + if (arg == Qnil) { + arg = rb_hash_new(); + } + gc_stat_internal(arg, 0); + return arg; +} + +size_t +rb_gc_stat(VALUE key) +{ + if (SYMBOL_P(key)) { + size_t value = 0; + gc_stat_internal(key, &value); + return value; + } else { + gc_stat_internal(key, 0); + return 0; + } +} + +/* + * call-seq: * GC.stress -> fixnum, true or false * * Returns current status of GC stress mode. |