# \[Feature #819\] Caching Symbol#to\_proc

**URL:** <https://www.ruby-forum.com/t/feature-819-caching-symbol-to-proc/154738>\
**Category:** Development\
**Created:** [December 3, 2008, 12:44pm UTC](https://www.ruby-forum.com/t/feature-819-caching-symbol-to-proc/154738 "2008-12-03T12:44:36Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shumpei\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@Shumpei\_A](https://www.ruby-forum.com/u/Shumpei_A)\
**Post date:** [December 3, 2008, 12:44pm UTC](https://www.ruby-forum.com/t/feature-819-caching-symbol-to-proc/154738/1 "2008-12-03T12:44:36Z")

</div>

Feature #819: Caching Symbol#to\_proc  
[http://redmine.ruby-lang.org/issues/show/819](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)

---

<div class="post-metadata">

**Author:** ![Shumpei\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@Shumpei\_A](https://www.ruby-forum.com/u/Shumpei_A)\
**Post date:** [December 4, 2008, 1:54am UTC](https://www.ruby-forum.com/t/feature-819-caching-symbol-to-proc/154738/2 "2008-12-04T01:54:30Z")

</div>

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@8@.D\>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. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

---

<div class="post-metadata">

**Author:** ![Shumpei\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@Shumpei\_A](https://www.ruby-forum.com/u/Shumpei_A)\
**Post date:** [December 4, 2008, 4:18am UTC](https://www.ruby-forum.com/t/feature-819-caching-symbol-to-proc/154738/3 "2008-12-04T04:18:51Z")

</div>

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@8@.D\>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

---

<div class="post-metadata">

**Author:** ![Shumpei\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@Shumpei\_A](https://www.ruby-forum.com/u/Shumpei_A)\
**Post date:** [December 4, 2008, 4:27pm UTC](https://www.ruby-forum.com/t/feature-819-caching-symbol-to-proc/154738/4 "2008-12-04T16:27:40Z")

</div>

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](http://redmine.ruby-lang.org/issues/show/819)

---

<div class="post-metadata">

**Author:** ![Shumpei\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@Shumpei\_A](https://www.ruby-forum.com/u/Shumpei_A)\
**Post date:** [December 4, 2008, 1:25pm UTC](https://www.ruby-forum.com/t/feature-819-caching-symbol-to-proc/154738/5 "2008-12-04T13:25:47Z")

</div>

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@8@.D\>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)  
{

---

<div class="post-metadata">

**Author:** ![Shumpei\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/6de8d8/32.png) [@Shumpei\_A](https://www.ruby-forum.com/u/Shumpei_A)\
**Post date:** [December 4, 2008, 4:33pm UTC](https://www.ruby-forum.com/t/feature-819-caching-symbol-to-proc/154738/6 "2008-12-04T16:33:34Z")

</div>

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
