[前][次][番号順一覧][スレッド一覧]

ruby-changes:39573

From: ko1 <ko1@a...>
Date: Fri, 21 Aug 2015 20:30:31 +0900 (JST)
Subject: [ruby-changes:39573] ko1:r51654 (trunk): * ext/objspace/objspace.c: add a new method ObjectSpace.count_symbols.

ko1	2015-08-21 20:30:24 +0900 (Fri, 21 Aug 2015)

  New Revision: 51654

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=51654

  Log:
    * ext/objspace/objspace.c: add a new method ObjectSpace.count_symbols.
      [Feature #11158]
    * symbol.c (rb_sym_immortal_count): added to count immortal symbols.
    * symbol.h: ditto.
    * test/objspace/test_objspace.rb: add a test for this method.
    * NEWS: describe about this method.

  Modified files:
    trunk/ChangeLog
    trunk/NEWS
    trunk/ext/objspace/objspace.c
    trunk/symbol.c
    trunk/symbol.h
    trunk/test/objspace/test_objspace.rb
Index: symbol.c
===================================================================
--- symbol.c	(revision 51653)
+++ symbol.c	(revision 51654)
@@ -864,6 +864,12 @@ rb_sym_all_symbols(void) https://github.com/ruby/ruby/blob/trunk/symbol.c#L864
     return ary;
 }
 
+size_t
+rb_sym_immortal_count(void)
+{
+    return (size_t)global_symbols.last_id;
+}
+
 int
 rb_is_const_id(ID id)
 {
Index: symbol.h
===================================================================
--- symbol.h	(revision 51653)
+++ symbol.h	(revision 51654)
@@ -100,4 +100,9 @@ is_global_name_punct(const int c) https://github.com/ruby/ruby/blob/trunk/symbol.h#L100
 
 ID rb_intern_cstr_without_pindown(const char *, long, rb_encoding *);
 
+RUBY_SYMBOL_EXPORT_BEGIN
+
+size_t rb_sym_immortal_count(void);
+
+RUBY_SYMBOL_EXPORT_END
 #endif
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 51653)
+++ ChangeLog	(revision 51654)
@@ -1,3 +1,16 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Fri Aug 21 19:58:48 2015  Koichi Sasada  <ko1@a...>
+
+	* ext/objspace/objspace.c: add a new method ObjectSpace.count_symbols.
+	  [Feature #11158]
+
+	* symbol.c (rb_sym_immortal_count): added to count immortal symbols.
+
+	* symbol.h: ditto.
+
+	* test/objspace/test_objspace.rb: add a test for this method.
+
+	* NEWS: describe about this method.
+
 Fri Aug 21 19:48:17 2015  Nobuyoshi Nakada  <nobu@r...>
 
 	* win32/Makefile.sub ($(LIBRUBY_SO)): needs additional libraries
Index: ext/objspace/objspace.c
===================================================================
--- ext/objspace/objspace.c	(revision 51653)
+++ ext/objspace/objspace.c	(revision 51654)
@@ -18,6 +18,7 @@ https://github.com/ruby/ruby/blob/trunk/ext/objspace/objspace.c#L18
 #include <ruby/re.h>
 #include "node.h"
 #include "gc.h"
+#include "symbol.h"
 
 /*
  *  call-seq:
@@ -249,6 +250,84 @@ count_objects_size(int argc, VALUE *argv https://github.com/ruby/ruby/blob/trunk/ext/objspace/objspace.c#L250
     return hash;
 }
 
+struct dynamic_symbol_counts {
+    size_t mortal;
+    size_t immortal;
+};
+
+static int
+cs_i(void *vstart, void *vend, size_t stride, void *n)
+{
+    struct dynamic_symbol_counts *counts = (struct dynamic_symbol_counts *)n;
+    VALUE v = (VALUE)vstart;
+
+    for (; v != (VALUE)vend; v += stride) {
+	if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_SYMBOL) {
+	    ID id = RSYMBOL(v)->id;
+	    if ((id & ~ID_SCOPE_MASK) == 0) {
+		counts->mortal++;
+	    }
+	    else {
+		counts->immortal++;
+	    }
+	}
+    }
+
+    return 0;
+}
+
+size_t rb_sym_immortal_count(void);
+
+/*
+ *  call-seq:
+ *     ObjectSpace.count_symbols([result_hash]) -> hash
+ *
+ *  Counts symbols for each Symbol type.
+ *
+ *  This method is only for MRI developers interested in performance and memory
+ *  usage of Ruby programs.
+ *
+ *  If the optional argument, result_hash, is given, it is overwritten and
+ *  returned. This is intended to avoid probe effect.
+ *
+ *  Note:
+ *  The contents of the returned hash is implementation defined.
+ *  It may be changed in future.
+ *
+ *  This method is only expected to work with C Ruby.
+ *
+ *  On this version of MRI, they have 3 types of Symbols (and 1 total counts).
+ *
+ *   * mortal_dynamic_symbol: GC target symbols (collected by GC)
+ *   * immortal_dynamic_symbol: Immortal symbols promoted from dynamic symbols (do not collected by GC)
+ *   * immortal_static_symbol: Immortal symbols (do not collected by GC)
+ *   * immortal_symbol: total immortal symbols (immortal_dynamic_symbol+immortal_static_symbol)
+ */
+
+static VALUE
+count_symbols(int argc, VALUE *argv, VALUE os)
+{
+    struct dynamic_symbol_counts dynamic_counts = {0, 0};
+    VALUE hash = setup_hash(argc, argv);
+
+    size_t immortal_symbols = rb_sym_immortal_count();
+    rb_objspace_each_objects(cs_i, &dynamic_counts);
+
+    if (hash == Qnil) {
+        hash = rb_hash_new();
+    }
+    else if (!RHASH_EMPTY_P(hash)) {
+        st_foreach(RHASH_TBL(hash), set_zero_i, hash);
+    }
+
+    rb_hash_aset(hash, ID2SYM(rb_intern("mortal_dynamic_symbol")),   SIZET2NUM(dynamic_counts.mortal));
+    rb_hash_aset(hash, ID2SYM(rb_intern("immortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.immortal));
+    rb_hash_aset(hash, ID2SYM(rb_intern("immortal_static_symbol")),  SIZET2NUM(immortal_symbols - dynamic_counts.immortal));
+    rb_hash_aset(hash, ID2SYM(rb_intern("immortal_symbol")),         SIZET2NUM(immortal_symbols));
+
+    return hash;
+}
+
 static int
 cn_i(void *vstart, void *vend, size_t stride, void *n)
 {
@@ -887,6 +966,7 @@ Init_objspace(void) https://github.com/ruby/ruby/blob/trunk/ext/objspace/objspace.c#L966
     rb_define_module_function(rb_mObjSpace, "memsize_of_all", memsize_of_all_m, -1);
 
     rb_define_module_function(rb_mObjSpace, "count_objects_size", count_objects_size, -1);
+    rb_define_module_function(rb_mObjSpace, "count_symbols", count_symbols, -1);
     rb_define_module_function(rb_mObjSpace, "count_nodes", count_nodes, -1);
     rb_define_module_function(rb_mObjSpace, "count_tdata_objects", count_tdata_objects, -1);
     rb_define_module_function(rb_mObjSpace, "count_imemo_objects", count_imemo_objects, -1);
Index: NEWS
===================================================================
--- NEWS	(revision 51653)
+++ NEWS	(revision 51654)
@@ -106,6 +106,7 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L106
     GC overhead
 
 * ObjectSpace (objspace)
+  * ObjectSpace.count_symbols is added.
   * ObjectSpace.count_imemo_objects is added.
   * ObjectSpace.internal_class_of is added.
   * ObjectSpace.internal_super_of is added.
Index: test/objspace/test_objspace.rb
===================================================================
--- test/objspace/test_objspace.rb	(revision 51653)
+++ test/objspace/test_objspace.rb	(revision 51654)
@@ -351,4 +351,15 @@ class TestObjSpace < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/objspace/test_objspace.rb#L351
     }
     assert_operator i, :>, 0
   end
+
+  def test_count_symbols
+    syms = (1..128).map{|i| ("xyzzy#{i}" * 128).to_sym}
+    c = Class.new{define_method(syms[-1]){}}
+
+    h = ObjectSpace.count_symbols
+    assert_operator h[:mortal_dynamic_symbol],   :>=, 128, h.inspect
+    assert_operator h[:immortal_dynamic_symbol], :>=, 1, h.inspect
+    assert_operator h[:immortal_static_symbol],  :>=, Object.methods.size, h.inspect
+    assert_equal h[:immortal_symbol], h[:immortal_dynamic_symbol] + h[:immortal_static_symbol], h.inspect
+  end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]