summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authortmm1 <tmm1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-12-05 07:45:13 +0000
committertmm1 <tmm1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-12-05 07:45:13 +0000
commit241c1a5459d986187ec42f166535d51b37202532 (patch)
tree27e697e24d024fab3242323d01e8644ee164e61d /gc.c
parent97ac1f6767745e97b136f9f0e1afd56903723f1a (diff)
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.c157
1 files changed, 101 insertions, 56 deletions
diff --git a/gc.c b/gc.c
index aec6828289..ac41c013a8 100644
--- a/gc.c
+++ b/gc.c
@@ -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.