[Feature #819] Caching Symbol#to_proc

Feature #819: Caching Symbol#to_proc
http://redmine.ruby-lang.org/issues/show/819

e$B5/I<<Te(B: Shumpei A.
e$B%9%F!<%?%9e(B: Open, e$BM%@hEYe(B: Normal

Symbol#to_proc
e$B$GKh2s%*%V%8%'%/%H$r@8@.$9$k$N$OL5BL$J5$$,$9$k$N$G!$e(B
e$B$$$/$D$+%-%c%C%7%e$7$F$O$I$&$G$7$g$&$+!%e(B

require ‘benchmark’
N=10000
syms_miss=(1…500).map{|i|“a#{i}”.to_sym}syms_hit=[:a]*500
Benchmark.bm do|r|
r.report(“miss”){N.times{syms_miss.each{|x|x.to_proc}}}
r.report(" hit"){N.times{syms_hit.each{|x|x.to_proc}}}
end

e$B>e$N$h$&$J%Y%s%A%^!<%/$r<h$k$H!$<!$N$h$&$K$J$j$^$9!%e(B
% ruby_trunk -v
ruby 1.9.1 (2008-12-03 patchlevel 5000 revision 20460) [x86_64-linux]

e$B%-%c%C%7%e$J$7e(B
user system total real
miss 9.060000 0.040000 9.100000 ( 9.092981)
hit 9.070000 0.050000 9.120000 ( 9.114511)
e$B%-%c%C%7%e$"$je(B
user system total real
miss 9.260000 0.020000 9.280000 ( 9.282089)
hit 0.750000 0.000000 0.750000 ( 0.757002)

e$B0J2<%Q%C%A$G$9e(B

Index: string.c

— string.c (e$B%j%S%8%g%se(B 20465)
+++ string.c (e$B:n6H%3%T!<e(B)
@@ -6912,13 +6912,37 @@

  • (1…3).collect(&:to_s) #=> [“1”, “2”, “3”]
    */

+static VALUE sym_proc_cache=Qfalse;
+#define SYM_PROC_CACHE_SIZE 64
static VALUE
sym_to_proc(VALUE sym)
{

  • return rb_proc_new(sym_call, (VALUE)SYM2ID(sym));
    -}
  • VALUE proc;

  • ID 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);
    
  • }

  • id=SYM2ID(sym);

  • 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)

e$B@1$H?=$7$^$9!#e(B

e$BF0:n3NG’$O$7$F$$$J$$$N$G$9$,!“e(B
sym_proc_cache e$B$N@[email protected]>8e$OD9$5e(B (len) 0 e$B$NG[Ns$J$N$Ge(B
sym_proc_cache e$B$NMWAG$Ne(B proc e$B%*%V%8%'%/%H$Oe(B
GC e$B$K2s<}$5$l$F$7$^$&62$l$,$”$k$N$G$O$J$$$G$7$g$&$+!#e(B

2008/12/3 Shumpei A. [email protected]:

e$B$J$+$@$G$9!#e(B

At Thu, 4 Dec 2008 09:48:10 +0900,
Hajime H. wrote in [ruby-dev:37267]:

e$BF0:n3NG’$O$7$F$$$J$$$N$G$9$,!“e(B
sym_proc_cache e$B$N@[email protected]>8e$OD9$5e(B (len) 0 e$B$NG[Ns$J$N$Ge(B
sym_proc_cache e$B$NMWAG$Ne(B proc e$B%*%V%8%’%/%H$Oe(B
GC e$B$K2s<}$5$l$F$7$^$&62$l$,$”$k$N$G$O$J$$$G$7$g$&$+!#e(B

e$B$=$l$H!“e(BIDe$B$O2<0L%S%C%H$G<oN`$rI=$7$F$$$k$N$GCM$KJP$j$,$”$j!"%-%c%Ce(B
e$B%7%e%5%$%:$,e(B2e$B$NQQ>h$@$H>WFM$9$k2DG=@-$,9b$/$J$j$^$9!#e(B

e$B%A%1%C%He(B #819 e$B$,99?7$5$l$^$7$?!#e(B (by Nobuyoshi N.)

e$B%9%F!<%?%9e(B Opene$B$+$ie(BClosede$B$KJQ99e(B
e$B?JD=e(B % 0e$B$+$ie(B100e$B$KJQ99e(B

Applied in changeset r20521.

http://redmine.ruby-lang.org/issues/show/819

e$B@V0f$G$9!%e(B

Hajime H. wrote, (2008/12/04 9:48):

e$BF0:n3NG’$O$7$F$$$J$$$N$G$9$,!“e(B
sym_proc_cache e$B$N@[email protected]>8e$OD9$5e(B (len) 0 e$B$NG[Ns$J$N$Ge(B
sym_proc_cache e$B$NMWAG$Ne(B proc e$B%*%V%8%’%/%H$Oe(B
GC e$B$K2s<}$5$l$F$7$^$&62$l$,$”$k$N$G$O$J$$$G$7$g$&$+!#e(B

Nobuyoshi N. wrote, (2008/12/04 12:12):

e$B$=$l$H!“e(BIDe$B$O2<0L%S%C%H$G<oN`$rI=$7$F$$$k$N$GCM$KJP$j$,$”$j!"%-%c%Ce(B
e$B%7%e%5%$%:$,e(B2e$B$NQQ>h$@$H>WFM$9$k2DG=@-$,9b$/$J$j$^$9!#e(B

e$BD>$9$J$i$3$N$h$&$J46$8$G$7$g$&$+!%e(B

Index: string.c

— string.c (e$B%j%S%8%g%se(B 20513)
+++ string.c (e$B:n6H%3%T!<e(B)
@@ -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)
{

e$B$J$+$@$G$9!#e(B

At Thu, 4 Dec 2008 21:19:24 +0900,
Shumpei A. wrote in [ruby-dev:37274]:

e$BD>$9$J$i$3$N$h$&$J46$8$G$7$g$&$+!%e(B

e$B0J2<$NE@$rJQ99$7$F%3%_%C%H$7$^$7$?!#e(B

  • RDoce$B$,:.Mp$9$k$N$rKI$0$?$a$Ke(Bsym_proc_cachee$B$r4X?tFb$K0$7$?e(B
  • rb_gc_register_mark_object()e$B$r;H$&e(B
  • ide$B$re(B3bite$B%7%U%H$9$k$H@5$7$/$J$$e(BProce$B$r:n$C$F$7$^$&e(B