* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51654 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
18d8ba2594
commit
885d781abc
13
ChangeLog
13
ChangeLog
@ -1,3 +1,16 @@
|
|||||||
|
Fri Aug 21 19:58:48 2015 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
|
* 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@ruby-lang.org>
|
Fri Aug 21 19:48:17 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* win32/Makefile.sub ($(LIBRUBY_SO)): needs additional libraries
|
* win32/Makefile.sub ($(LIBRUBY_SO)): needs additional libraries
|
||||||
|
1
NEWS
1
NEWS
@ -106,6 +106,7 @@ with all sufficient information, see the ChangeLog file.
|
|||||||
GC overhead
|
GC overhead
|
||||||
|
|
||||||
* ObjectSpace (objspace)
|
* ObjectSpace (objspace)
|
||||||
|
* ObjectSpace.count_symbols is added.
|
||||||
* ObjectSpace.count_imemo_objects is added.
|
* ObjectSpace.count_imemo_objects is added.
|
||||||
* ObjectSpace.internal_class_of is added.
|
* ObjectSpace.internal_class_of is added.
|
||||||
* ObjectSpace.internal_super_of is added.
|
* ObjectSpace.internal_super_of is added.
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <ruby/re.h>
|
#include <ruby/re.h>
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "gc.h"
|
#include "gc.h"
|
||||||
|
#include "symbol.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
@ -249,6 +250,84 @@ count_objects_size(int argc, VALUE *argv, VALUE os)
|
|||||||
return hash;
|
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
|
static int
|
||||||
cn_i(void *vstart, void *vend, size_t stride, void *n)
|
cn_i(void *vstart, void *vend, size_t stride, void *n)
|
||||||
{
|
{
|
||||||
@ -887,6 +966,7 @@ Init_objspace(void)
|
|||||||
rb_define_module_function(rb_mObjSpace, "memsize_of_all", memsize_of_all_m, -1);
|
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_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_nodes", count_nodes, -1);
|
||||||
rb_define_module_function(rb_mObjSpace, "count_tdata_objects", count_tdata_objects, -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);
|
rb_define_module_function(rb_mObjSpace, "count_imemo_objects", count_imemo_objects, -1);
|
||||||
|
6
symbol.c
6
symbol.c
@ -864,6 +864,12 @@ rb_sym_all_symbols(void)
|
|||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
rb_sym_immortal_count(void)
|
||||||
|
{
|
||||||
|
return (size_t)global_symbols.last_id;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rb_is_const_id(ID id)
|
rb_is_const_id(ID id)
|
||||||
{
|
{
|
||||||
|
5
symbol.h
5
symbol.h
@ -100,4 +100,9 @@ is_global_name_punct(const int c)
|
|||||||
|
|
||||||
ID rb_intern_cstr_without_pindown(const char *, long, rb_encoding *);
|
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
|
#endif
|
||||||
|
@ -351,4 +351,15 @@ class TestObjSpace < Test::Unit::TestCase
|
|||||||
}
|
}
|
||||||
assert_operator i, :>, 0
|
assert_operator i, :>, 0
|
||||||
end
|
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
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user