From: nobu.nakada@... Date: 2002-01-17T21:26:16+09:00 Subject: [ruby-dev:15705] Re: method cache なかだです。 At Thu, 17 Jan 2002 20:42:42 +0900, Takaaki Tateishi wrote: > > |その場合,定義したメソッドのIDがキャッシュされている可能性があ > > |る場合にのみ全探索してエントリを削除するというように変更すると, > > |多少スピードが上がるようです. > > > > 基本的なアイディアは評価できますが、CACHE_DAMAGEはクリアして > > はいけないような気がします(たまたま同じスロットを使うIDも > > DAMAGEを受けているかもしれないので)。 > > 気づいてませんでした.確かにまずいですね. > rb_clear_cache_by_id()については,cache_damageでカウントしておいて, > 2度以上damageを受ける(同じスロットが異なるidで使われる可能性がある) > とundamageできないようにしておくというのはどうでしょう? > そして,rb_clear_cache()の場合には全部undamageします. > この方法でsample/test.rbを実行しても,ほとんど実行時間は変わらないよ > うです. > > # 他の方法としてはハッシュですべてのdamageを受けたIDを覚えておくとい > # うくらいでしょうか… ちょっと試してみましたが、結構微妙です。 Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.245 diff -u -2 -p -r1.245 eval.c --- eval.c 2002/01/16 09:32:51 1.245 +++ eval.c 2002/01/17 12:01:37 @@ -188,4 +188,23 @@ struct cache_entry { /* method hash tab static struct cache_entry cache[CACHE_SIZE]; +#if CACHE_DAMAGE_TYPE == 1 +static int cache_damage[CACHE_SIZE]; +#define CACHE_DAMAGE(id) (cache_damage[(id)&CACHE_MASK]++) +#define CACHE_UNDAMAGE(id) (cache_damage[(id)&CACHE_MASK] == 1 && cache_damage[(id)&CACHE_MASK] = 0) +#define CACHE_DAMAGED_P(id) (cache_damage[(id)&CACHE_MASK]) +#define CACHE_CLEAR_DAMAGE() memset(cache_damage, 0, sizeof cache_damage) +#elif CACHE_DAMAGE_TYPE == 2 +static ID cache_damage[CACHE_SIZE]; +#define CACHE_DAMAGE(id) (cache_damage[(id)&CACHE_MASK] = (id)) +#define CACHE_UNDAMAGE(id) (cache_damage[(id)&CACHE_MASK] = 0) +#define CACHE_DAMAGED_P(id) (cache_damage[(id)&CACHE_MASK] == (id)) +#define CACHE_CLEAR_DAMAGE() memset(cache_damage, 0, sizeof cache_damage) +#else +#define CACHE_DAMAGE(id) ((void)(id)) +#define CACHE_UNDAMAGE(id) ((void)(id)) +#define CACHE_DAMAGED_P(id) (1) +#define CACHE_CLEAR_DAMAGE() ((void)0) +#endif + void rb_clear_cache() @@ -198,4 +217,5 @@ rb_clear_cache() ent++; } + CACHE_CLEAR_DAMAGE(); } @@ -206,4 +226,6 @@ rb_clear_cache_by_id(id) struct cache_entry *ent, *end; + if (!CACHE_DAMAGED_P(id)) return; + CACHE_UNDAMAGE(id); ent = cache; end = ent + CACHE_SIZE; while (ent < end) { @@ -266,4 +288,5 @@ rb_get_method_body(klassp, idp, noexp) /* store empty info in cache */ ent = cache + EXPR1(klass, id); + CACHE_DAMAGE(id); ent->klass = klass; ent->origin = klass; @@ -277,4 +300,5 @@ rb_get_method_body(klassp, idp, noexp) /* store in cache */ ent = cache + EXPR1(klass, id); + CACHE_DAMAGE(id); ent->klass = klass; ent->noex = body->nd_noex; @@ -4628,4 +4652,5 @@ rb_call(klass, recv, mid, argc, argv, sc ent = cache + EXPR1(klass, mid); if (ent->mid == mid && ent->klass == klass) { + CACHE_DAMAGE(id); if (!ent->method) return rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0); -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦