Feature #1597
closedObjectSpace.count_nodes
Description
=begin
ささだです.
ObjectSpace.count_objects という,オブジェクトの種類を数えるメソッドが
ありますが,同じように ObjectSpace.count_nodes というものを加えるのはど
うでしょうか.
いや,使うのは多分 Ruby 開発者だけのような気もするので,正直どうかなぁ
とも思うんですが.
slot を全部巡る, st_each みたいなインターフェースがあれば,¶
拡張ライブラリとして実装することも不可能じゃなくなる,¶
けど,コールバックベースだと遅いかもなあ.¶
利用例:
例えば benchmark/bm_pentomino.rb を実行すると,なんか node が沢山出来
ているのが分かるの (*1) で,なぜだろうかと解析することが出来ます (*2).
*1:
http://www.atdot.net/fp_store/f.89p1lk/file.g.png
X軸が時間,左Y軸がオブジェクト数,右Y軸がGC回数
1秒ごとのサンプリング.
node の数が GC 回数に影響していることがわかる
*2:
http://www.atdot.net/fp_store/f.eio1lk/file.g.png
X軸が時間,Y軸が消費量・GC回数
1秒ごとのサンプリング.
ほぼ,NODE_LITの生成回数にGC回数が依存していることがわかる.
NODE_LIT は,実は break 時にテンポラリオブジェクトとして生成される
んだけど,pentomino では break を沢山するので,こういうことになる,
ということがわかった.
余談:¶
じゃぁ,break の実装を変えれば性能が向上するかというと,¶
GC の実行時間は1秒中0.1秒くらいなので,1割の性能向上が見込める,¶
かもしれない.¶
+static VALUE
+count_nodes(int argc, VALUE *argv, VALUE os)
+{
- rb_objspace_t *objspace = &rb_objspace;
- size_t nodes[NODE_LAST];
- size_t i;
- VALUE hash;
- if (rb_scan_args(argc, argv, "01", &hash) == 1) {
-
if (TYPE(hash) != T_HASH) -
rb_raise(rb_eTypeError, "non-hash given"); - }
- for (i = 0; i <= NODE_LAST; i++) {
- nodes[i] = 0;
- }
- for (i = 0; i < heaps_used; i++) {
-
RVALUE *p, *pend; -
p = heaps[i].slot; pend = p + heaps[i].limit; -
for (;p < pend; p++) { -
if (p->as.basic.flags && BUILTIN_TYPE(p) == T_NODE) { -
nodes[nd_type((NODE *)p)]++; -
} - }
- }
- if (hash == Qnil) {
-
hash = rb_hash_new(); - }
- else if (!RHASH_EMPTY_P(hash)) {
-
st_foreach(RHASH_TBL(hash), set_zero, hash); - }
- for (i=0; i<NODE_LAST; i++) {
- if (nodes[i] != 0) {
-
VALUE node; -
switch (i) {
+#define COUNT_NODE(n) case n: node = ID2SYM(rb_intern(#n)); break;
-
COUNT_NODE(NODE_METHOD); -
COUNT_NODE(NODE_FBODY); -
COUNT_NODE(NODE_CFUNC); -
COUNT_NODE(NODE_SCOPE); -
COUNT_NODE(NODE_BLOCK); -
COUNT_NODE(NODE_IF); -
COUNT_NODE(NODE_CASE); -
COUNT_NODE(NODE_WHEN); -
COUNT_NODE(NODE_OPT_N); -
COUNT_NODE(NODE_WHILE); -
COUNT_NODE(NODE_UNTIL); -
COUNT_NODE(NODE_ITER); -
COUNT_NODE(NODE_FOR); -
COUNT_NODE(NODE_BREAK); -
COUNT_NODE(NODE_NEXT); -
COUNT_NODE(NODE_REDO); -
COUNT_NODE(NODE_RETRY); -
COUNT_NODE(NODE_BEGIN); -
COUNT_NODE(NODE_RESCUE); -
COUNT_NODE(NODE_RESBODY); -
COUNT_NODE(NODE_ENSURE); -
COUNT_NODE(NODE_AND); -
COUNT_NODE(NODE_OR); -
COUNT_NODE(NODE_MASGN); -
COUNT_NODE(NODE_LASGN); -
COUNT_NODE(NODE_DASGN); -
COUNT_NODE(NODE_DASGN_CURR); -
COUNT_NODE(NODE_GASGN); -
COUNT_NODE(NODE_IASGN); -
COUNT_NODE(NODE_IASGN2); -
COUNT_NODE(NODE_CDECL); -
COUNT_NODE(NODE_CVASGN); -
COUNT_NODE(NODE_CVDECL); -
COUNT_NODE(NODE_OP_ASGN1); -
COUNT_NODE(NODE_OP_ASGN2); -
COUNT_NODE(NODE_OP_ASGN_AND); -
COUNT_NODE(NODE_OP_ASGN_OR); -
COUNT_NODE(NODE_CALL); -
COUNT_NODE(NODE_FCALL); -
COUNT_NODE(NODE_VCALL); -
COUNT_NODE(NODE_SUPER); -
COUNT_NODE(NODE_ZSUPER); -
COUNT_NODE(NODE_ARRAY); -
COUNT_NODE(NODE_ZARRAY); -
COUNT_NODE(NODE_VALUES); -
COUNT_NODE(NODE_HASH); -
COUNT_NODE(NODE_RETURN); -
COUNT_NODE(NODE_YIELD); -
COUNT_NODE(NODE_LVAR); -
COUNT_NODE(NODE_DVAR); -
COUNT_NODE(NODE_GVAR); -
COUNT_NODE(NODE_IVAR); -
COUNT_NODE(NODE_CONST); -
COUNT_NODE(NODE_CVAR); -
COUNT_NODE(NODE_NTH_REF); -
COUNT_NODE(NODE_BACK_REF); -
COUNT_NODE(NODE_MATCH); -
COUNT_NODE(NODE_MATCH2); -
COUNT_NODE(NODE_MATCH3); -
COUNT_NODE(NODE_LIT); -
COUNT_NODE(NODE_STR); -
COUNT_NODE(NODE_DSTR); -
COUNT_NODE(NODE_XSTR); -
COUNT_NODE(NODE_DXSTR); -
COUNT_NODE(NODE_EVSTR); -
COUNT_NODE(NODE_DREGX); -
COUNT_NODE(NODE_DREGX_ONCE); -
COUNT_NODE(NODE_ARGS); -
COUNT_NODE(NODE_ARGS_AUX); -
COUNT_NODE(NODE_OPT_ARG); -
COUNT_NODE(NODE_POSTARG); -
COUNT_NODE(NODE_ARGSCAT); -
COUNT_NODE(NODE_ARGSPUSH); -
COUNT_NODE(NODE_SPLAT); -
COUNT_NODE(NODE_TO_ARY); -
COUNT_NODE(NODE_BLOCK_ARG); -
COUNT_NODE(NODE_BLOCK_PASS); -
COUNT_NODE(NODE_DEFN); -
COUNT_NODE(NODE_DEFS); -
COUNT_NODE(NODE_ALIAS); -
COUNT_NODE(NODE_VALIAS); -
COUNT_NODE(NODE_UNDEF); -
COUNT_NODE(NODE_CLASS); -
COUNT_NODE(NODE_MODULE); -
COUNT_NODE(NODE_SCLASS); -
COUNT_NODE(NODE_COLON2); -
COUNT_NODE(NODE_COLON3); -
COUNT_NODE(NODE_DOT2); -
COUNT_NODE(NODE_DOT3); -
COUNT_NODE(NODE_FLIP2); -
COUNT_NODE(NODE_FLIP3); -
COUNT_NODE(NODE_ATTRSET); -
COUNT_NODE(NODE_SELF); -
COUNT_NODE(NODE_NIL); -
COUNT_NODE(NODE_TRUE); -
COUNT_NODE(NODE_FALSE); -
COUNT_NODE(NODE_ERRINFO); -
COUNT_NODE(NODE_DEFINED); -
COUNT_NODE(NODE_POSTEXE); -
COUNT_NODE(NODE_ALLOCA); -
COUNT_NODE(NODE_BMETHOD); -
COUNT_NODE(NODE_MEMO); -
COUNT_NODE(NODE_IFUNC); -
COUNT_NODE(NODE_DSYM); -
COUNT_NODE(NODE_ATTRASGN); -
COUNT_NODE(NODE_PRELUDE); -
COUNT_NODE(NODE_LAMBDA); -
COUNT_NODE(NODE_OPTBLOCK);
+#undef COUNT_NODE
-
default: node = INT2FIX(nodes[i]); -
} -
rb_hash_aset(hash, node, SIZET2NUM(nodes[i])); - }
- }
- return hash;
+}
--
// SASADA Koichi at atdot dot net
=end
Updated by matz (Yukihiro Matsumoto) over 16 years ago
=begin
まつもと ゆきひろです
In message "Re: [ruby-dev:38584] [Feature: trunk] ObjectSpace.count_nodes"
on Thu, 11 Jun 2009 08:05:56 +0900, SASADA Koichi ko1@atdot.net writes:
| ObjectSpace.count_objects という,オブジェクトの種類を数えるメソッドが
|ありますが,同じように ObjectSpace.count_nodes というものを加えるのはど
|うでしょうか.
|
| いや,使うのは多分 Ruby 開発者だけのような気もするので,正直どうかなぁ
|とも思うんですが.
「nodeが存在する」というのは特定の実装に依存する話ですので、
メソッドとして追加するのはどうかと思います。関数を用意して
おいて、拡張ライブラリでメソッドとして登録するならありなんじゃ
ないかなあ。
=end
Updated by yugui (Yuki Sonoda) over 16 years ago
- Assignee set to ko1 (Koichi Sasada)
- Target version set to 2.0.0
=begin
=end
Updated by naruse (Yui NARUSE) about 16 years ago
- Status changed from Open to Rejected
=begin
=end