From: Shumpei Akai Date: 2008-12-04T21:19:24+09:00 Subject: [ruby-dev:37274] Re: [Feature #819] Caching Symbol#to_proc 赤井です. Hajime Hoshi wrote, (2008/12/04 9:48): > 動作確認はしていないのですが、 > sym_proc_cache の生成直後は長さ (len) 0 の配列なので > sym_proc_cache の要素の proc オブジェクトは > GC に回収されてしまう恐れがあるのではないでしょうか。 Nobuyoshi Nakada wrote, (2008/12/04 12:12): > それと、IDは下位ビットで種類を表しているので値に偏りがあり、キャッ > シュサイズが2の冪乗だと衝突する可能性が高くなります。 直すならこのような感じでしょうか. Index: string.c =================================================================== --- string.c (リビジョン 20513) +++ string.c (作業コピー) @@ -6912,13 +6912,38 @@ * (1..3).collect(&:to_s) #=> ["1", "2", "3"] */ +static VALUE sym_proc_cache=Qfalse; +#define SYM_PROC_CACHE_SIZE 67 static VALUE sym_to_proc(VALUE sym) { - return rb_proc_new(sym_call, (VALUE)SYM2ID(sym)); -} + VALUE proc; + long id; + long sym_index,proc_index; + VALUE *aryp; + if(!sym_proc_cache){ + rb_global_variable(&sym_proc_cache); + sym_proc_cache = rb_ary_new2(SYM_PROC_CACHE_SIZE * 2); + rb_ary_store(sym_proc_cache, SYM_PROC_CACHE_SIZE*2 - 1, Qnil); + } + + id=SYM2ID(sym)>>3; + sym_index= (id % SYM_PROC_CACHE_SIZE) << 1; + proc_index = sym_index | 1; + + aryp=RARRAY_PTR(sym_proc_cache); + if(aryp[sym_index]==sym){ + return aryp[proc_index]; + }else{ + proc = rb_proc_new(sym_call, (VALUE)id); + aryp[sym_index]=sym; + aryp[proc_index]=proc; + return proc; + } +} + static VALUE sym_succ(VALUE sym) { -- 赤井駿平