Project

General

Profile

Feature #1597

ObjectSpace.count_nodes

Added by ko1 (Koichi Sasada) almost 9 years ago. Updated almost 7 years ago.

Status:
Rejected
Priority:
Normal
Target version:
[ruby-dev:38584]

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

History

#1 Updated by matz (Yukihiro Matsumoto) almost 9 years ago

=begin
まつもと ゆきひろです

In message "Re: [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

#2 Updated by yugui (Yuki Sonoda) almost 9 years ago

  • Assignee set to ko1 (Koichi Sasada)
  • Target version set to 2.0.0

=begin

=end

#3 Updated by naruse (Yui NARUSE) over 8 years ago

  • Status changed from Open to Rejected

=begin

=end

Also available in: Atom PDF