# Contest: fastet way to redefine a method

**URL:** <https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037>\
**Category:** ruby-talk\
**Created:** [27 December 2006 16:59 UTC](https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037 "2006-12-27T16:59:58Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Pit](https://avatars.discourse-cdn.com/v4/letter/p/f14d63/32.png) [@Pit](https://rubytalk.org/u/Pit)\
**Post date:** [27 December 2006 16:59 UTC](https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037/1 "2006-12-27T16:59:58Z")

</div>

Hi,

Dan Berger's recent thread about using UnboundMethod#bind to redefine an existing method reminded me of a problem I still have:

&nbsp;&nbsp;&nbsp;What is the fastest way to redefine an existing method?

With "fast" I don't mean the process of redefining the method, but the time it takes to actually call the new implementation.

With "redefining an existing method" I mean changing the implementation of an existing method so that in the new implementation it is possible to call the old one and use its return value.

I've seen many different techniques in the past here on ruby-talk, but I haven't looked at the tradeoffs. I promise to write a page on the ruby garden wiki with the results.

Regards,  
Pit

---

<div class="post-metadata">

**Author:** ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)\
**Post date:** [27 December 2006 18:08 UTC](https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037/2 "2006-12-27T18:08:59Z")

</div>

Pit Capitain wrote:

> Hi,
> 
> Dan Berger's recent thread about using UnboundMethod#bind to redefine an  
> existing method reminded me of a problem I still have:
> 
> &nbsp;&nbsp;&nbsp;What is the fastest way to redefine an existing method?
> 
> With "fast" I don't mean the process of redefining the method, but the  
> time it takes to actually call the new implementation.
> 
> With "redefining an existing method" I mean changing the implementation  
> of an existing method so that in the new implementation it is possible  
> to call the old one and use its return value.
> 
> I've seen many different techniques in the past here on ruby-talk, but I  
> haven't looked at the tradeoffs. I promise to write a page on the ruby  
> garden wiki with the results.
> 
> Regards,  
> Pit

A cut is going to be just about the fastest I think since it is  
essentially a subclass, although defining the "wrapping" method  
requires a bit of additional overhead. Alias certainly has the least  
overhead. I imagine before and after wraps as matz has suggested for  
Ruby 2.0 would be faster, albiet they are more limited in capability  
than cuts.

Keep in mind that every "wrap" will have a benchmark greater than the  
orginal by neccessity b/c includes the originals call --so what's  
really of interest is the difference from the original. Consdiering  
that it is clear what the fastest way would be. To literally extract  
the source code of the oringal method and wrap it via string  
manipulation and eval the result as the new method. Of course, that's  
not all that practical -- for starters I think you would need something  
like ParseTree to even pull it off.

Anyway here's Ara's benchmarks with cuts/subclass added:

> **···**
>
> #  
> # Alias  
> #  
> class HashUsingAlias \< Hash  
> &nbsp;&nbsp;&nbsp;&nbsp;alias :old\_hset :=
> 
> &nbsp;&nbsp;&nbsp;&nbsp;def =(key, value)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.old\_hset(key, value)  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> end
> 
> #  
> # Bind  
> #  
> class HashUsingBind \< Hash  
> &nbsp;&nbsp;&nbsp;&nbsp;hset = self.instance\_method(:=)
> 
> &nbsp;&nbsp;&nbsp;&nbsp;define\_method(:=) do |key, value|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hset.bind(self).call(key, value)  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> end
> 
> #  
> # Override  
> #  
> require 'override'  
> class HashUsingOverride \< Hash  
> &nbsp;&nbsp;&nbsp;override('='){ def =(k,v) super end }  
> end
> 
> #  
> # Subclass  
> #  
> class HashUsingSubClass \< Hash  
> &nbsp;&nbsp;def =(k,v)  
> &nbsp;&nbsp;&nbsp;&nbsp;super  
> &nbsp;&nbsp;end  
> end
> 
> #  
> # Cut (pure ruby meta-hacking version)  
> #  
> require 'facets/more/cut'  
> class HashUsingCut \< Hash; end
> 
> cut :HashUsingCutAspect \< HashUsingCut do  
> &nbsp;&nbsp;def =(k,v); super; end  
> end
> 
> require "benchmark"  
> def bm\_report bm, title, hash\_class  
> &nbsp;&nbsp;&nbsp;hash = hash\_class.new  
> &nbsp;&nbsp;&nbsp;bm.report title do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;100\_000.times do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash[1] = 1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;end  
> end
> 
> Benchmark.bmbm do |bm|  
> &nbsp;&nbsp;&nbsp;bm\_report bm, "original", Hash  
> &nbsp;&nbsp;&nbsp;bm\_report bm, "alias", HashUsingAlias  
> &nbsp;&nbsp;&nbsp;bm\_report bm, "bind", HashUsingBind  
> &nbsp;&nbsp;&nbsp;bm\_report bm, "override", HashUsingOverride  
> &nbsp;&nbsp;&nbsp;bm\_report bm, "subclass", HashUsingSubClass  
> &nbsp;&nbsp;&nbsp;bm\_report bm, "cut", HashUsingCut  
> end
> 
> Rehearsal --------------------------------------------  
> original 0.100000 0.020000 0.120000 ( 0.125107)  
> alias 0.180000 0.030000 0.210000 ( 0.226911)  
> bind 0.460000 0.050000 0.510000 ( 0.525037)  
> override 0.590000 0.030000 0.620000 ( 0.630301)  
> subclass 0.170000 0.030000 0.200000 ( 0.210436)  
> cut 0.170000 0.030000 0.200000 ( 0.210003)  
> ----------------------------------- total: 1.860000sec
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user system total real  
> original 0.100000 0.010000 0.110000 ( 0.123498)  
> alias 0.170000 0.040000 0.210000 ( 0.224580)  
> bind 0.480000 0.030000 0.510000 ( 0.529366)  
> override 0.570000 0.050000 0.620000 ( 0.626580)  
> subclass 0.170000 0.030000 0.200000 ( 0.214458)  
> cut 0.170000 0.030000 0.200000 ( 0.209727)

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [27 December 2006 18:20 UTC](https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037/3 "2006-12-27T18:20:06Z")

</div>

> &nbsp;&nbsp;What is the fastest way to redefine an existing method?
> 
> With "fast" I don't mean the process of redefining the method, but the time it takes to actually call the new implementation.

So you mean runtime efficiency.

> With "redefining an existing method" I mean changing the implementation of an existing method so that in the new implementation it is possible to call the old one and use its return value.

I once cooked something together. The code is on Ruby Garden:  
[http://wiki.rubygarden.org/Ruby/page/show/MethodHooks](http://wiki.rubygarden.org/Ruby/page/show/MethodHooks)

No idea about performance etc. At some point I stopped working on this because it was said that Ruby 2 will include a feature for this. I remember that there were some limitations (i.e. no suppport for blocks so far) but usability is ok IMHO. This was mostly an experiment.

Kind regards

&nbsp;&nbsp;robert

> **···**
>
> On 27.12.2006 17:59, Pit Capitain wrote:

---

<div class="post-metadata">

**Author:** ![Eric\_Hodel1](https://avatars.discourse-cdn.com/v4/letter/e/a9adbd/32.png) [@Eric\_Hodel1](https://rubytalk.org/u/Eric_Hodel1)\
**Post date:** [27 December 2006 22:09 UTC](https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037/4 "2006-12-27T22:09:55Z")

</div>

I already did this:

[http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-define\_method](http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-define_method)

You can probably match def for speed by using one of the eval methods.

> **···**
>
> On Dec 27, 2006, at 08:59, Pit Capitain wrote:
> 
> > Dan Berger's recent thread about using UnboundMethod#bind to redefine an existing method reminded me of a problem I still have:
> > 
> > &nbsp;&nbsp;What is the fastest way to redefine an existing method?
> > 
> > With "fast" I don't mean the process of redefining the method, but the time it takes to actually call the new implementation.
> > 
> > With "redefining an existing method" I mean changing the implementation of an existing method so that in the new implementation it is possible to call the old one and use its return value.
> > 
> > I've seen many different techniques in the past here on ruby-talk, but I haven't looked at the tradeoffs. I promise to write a page on the ruby garden wiki with the results.
> 
> --  
> Eric Hodel - drbrain@segment7.net - [http://blog.segment7.net](http://blog.segment7.net)
> 
> I LIT YOUR GEM ON FIRE!

---

<div class="post-metadata">

**Author:** ![Ara.T.Howard6](https://avatars.discourse-cdn.com/v4/letter/a/958977/32.png) [@Ara.T.Howard6](https://rubytalk.org/u/Ara.T.Howard6)\
**Post date:** [27 December 2006 22:26 UTC](https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037/5 "2006-12-27T22:26:49Z")

</div>

did you mean to say 'evil methods' 😉

-a

> **···**
>
> On Thu, 28 Dec 2006, Eric Hodel wrote:
> 
> > I already did this:
> > 
> > [http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-define\_method](http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-define_method)
> > 
> > You can probably match def for speed by using one of the eval methods.
> 
> --  
> if you find yourself slandering anybody, first imagine that your mouth is  
> filled with excrement. it will break you of the habit quickly enough. - the  
> dalai lama

---

<div class="post-metadata">

**Author:** ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)\
**Post date:** [28 December 2006 00:35 UTC](https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037/6 "2006-12-28T00:35:08Z")

</div>

Post Not Found....

> **···**
>
> On Dec 27, 5:09 pm, Eric Hodel \<drbr...@segment7.net\> wrote:
> 
> > [http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-](http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-)  
> > define\_method

---

<div class="post-metadata">

**Author:** ![Pit](https://avatars.discourse-cdn.com/v4/letter/p/f14d63/32.png) [@Pit](https://rubytalk.org/u/Pit)\
**Post date:** [28 December 2006 08:27 UTC](https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037/7 "2006-12-28T08:27:03Z")

</div>

Eric Hodel schrieb:

> > I promise to write a page on the ruby garden wiki with the results.
> 
> I already did this:
> 
> [http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-define\_method](http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-define_method)

Eric, thanks for the link. I'm sure these numbers will help, but they are not exactly what I'm looking for. I'm looking for different techniques to redefine a method in a way that still allows to call the previous implementation. Personally, I'm mostly interested in fast techniques, so your benchmark is very welcome.

Regards,  
Pit

> **···**
>
> > On Dec 27, 2006, at 08:59, Pit Capitain wrote:

---

<div class="post-metadata">

**Author:** ![Eric\_Hodel1](https://avatars.discourse-cdn.com/v4/letter/e/a9adbd/32.png) [@Eric\_Hodel1](https://rubytalk.org/u/Eric_Hodel1)\
**Post date:** [27 December 2006 22:47 UTC](https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037/8 "2006-12-27T22:47:36Z")

</div>

There's no need to use the evil eval:

$ parse\_tree\_show  
class X; class\_eval { def y() 5; end } end  
[[:class,  
&nbsp;&nbsp;&nbsp;:X,  
&nbsp;&nbsp;&nbsp;[:const, :Object],  
&nbsp;&nbsp;&nbsp;[:defn, :y, [:scope, [:block, [:args], [:lit, 5]]]]]]

Which generates the same AST as a regular def:

$ parse\_tree\_show  
class X; def y() 5; end; end  
[[:class,  
&nbsp;&nbsp;&nbsp;:X,  
&nbsp;&nbsp;&nbsp;[:const, :Object],  
&nbsp;&nbsp;&nbsp;[:defn, :y, [:scope, [:block, [:args], [:lit, 5]]]]]]

If you use alias, the aliased method will be slightly slower:

$ parse\_tree\_show  
class X; def y(); 5 end; alias x y; end  
[[:class,  
&nbsp;&nbsp;&nbsp;:X,  
&nbsp;&nbsp;&nbsp;[:const, :Object],  
&nbsp;&nbsp;&nbsp;[:defn, :x, [:fbody, [:scope, [:block, [:args], [:lit, 5]]]]],  
&nbsp;&nbsp;&nbsp;[:defn, :y, [:scope, [:block, [:args], [:lit, 5]]]]]]

But you can use ruby2ruby to regenerate the aliased method without the :fbody node (or, just inline it). I'll leave this as an exercise to the reader.

> **···**
>
> On Dec 27, 2006, at 14:26, ara.t.howard@noaa.gov wrote:
> 
> > On Thu, 28 Dec 2006, Eric Hodel wrote:
> > 
> > > I already did this:
> > > 
> > > [http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-define\_method](http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-define_method)
> > > 
> > > You can probably match def for speed by using one of the eval methods.
> > 
> > did you mean to say 'evil methods' 😉
> 
> --  
> Eric Hodel - drbrain@segment7.net - [http://blog.segment7.net](http://blog.segment7.net)
> 
> I LIT YOUR GEM ON FIRE!

---

<div class="post-metadata">

**Author:** ![Eric\_Hodel1](https://avatars.discourse-cdn.com/v4/letter/e/a9adbd/32.png) [@Eric\_Hodel1](https://rubytalk.org/u/Eric_Hodel1)\
**Post date:** [28 December 2006 02:03 UTC](https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037/9 "2006-12-28T02:03:26Z")

</div>

Lies.

> **···**
>
> On Dec 27, 2006, at 16:35, Trans wrote:
> 
> > > [http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-define\_method](http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-define_method)
> 
> --  
> Eric Hodel - drbrain@segment7.net - [http://blog.segment7.net](http://blog.segment7.net)
> 
> I LIT YOUR GEM ON FIRE!

---

<div class="post-metadata">

**Author:** ![Mat\_Schaffer](https://avatars.discourse-cdn.com/v4/letter/m/71e660/32.png) [@Mat\_Schaffer](https://rubytalk.org/u/Mat_Schaffer)\
**Post date:** [28 December 2006 04:08 UTC](https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037/10 "2006-12-28T04:08:44Z")

</div>

Looks like your mail reader is inserting hard line breaks.  
-Mat

> **···**
>
> On Dec 27, 2006, at 7:35 PM, Trans wrote:
> 
> > On Dec 27, 5:09 pm, Eric Hodel \<drbr...@segment7.net\> wrote:
> > 
> > > [http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-](http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-)  
> > > define\_method
> > 
> > Post Not Found....

---

<div class="post-metadata">

**Author:** ![Ara.T.Howard6](https://avatars.discourse-cdn.com/v4/letter/a/958977/32.png) [@Ara.T.Howard6](https://rubytalk.org/u/Ara.T.Howard6)\
**Post date:** [27 December 2006 23:10 UTC](https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037/11 "2006-12-27T23:10:57Z")

</div>

sorry - just trying to be punny!

-a

> **···**
>
> On Thu, 28 Dec 2006, Eric Hodel wrote:
> 
> > On Dec 27, 2006, at 14:26, ara.t.howard@noaa.gov wrote:
> > 
> > > On Thu, 28 Dec 2006, Eric Hodel wrote:
> > > 
> > > > I already did this:
> > > > 
> > > > [http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-](http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-) define\_method
> > > > 
> > > > You can probably match def for speed by using one of the eval methods.
> > > 
> > > did you mean to say 'evil methods' 😉
> > 
> > There's no need to use the evil eval:
> 
> --  
> if you find yourself slandering anybody, first imagine that your mouth is  
> filled with excrement. it will break you of the habit quickly enough. - the  
> dalai lama

---

<div class="post-metadata">

**Author:** ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)\
**Post date:** [28 December 2006 05:29 UTC](https://rubytalk.org/t/contest-fastet-way-to-redefine-a-method/34037/12 "2006-12-28T05:29:22Z")

</div>

Mat Schaffer wrote:

> **···**
>
> > On Dec 27, 2006, at 7:35 PM, Trans wrote:  
> > \> On Dec 27, 5:09 pm, Eric Hodel \<drbr...@segment7.net\> wrote:  
> > \>\>  
> > \>\> [http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-](http://blog.segment7.net/articles/2006/03/06/attr-vs-method-vs-)  
> > \>\> define\_method  
> > \>  
> > \> Post Not Found....
> > 
> > Looks like your mail reader is inserting hard line breaks.
> 
> Interesting I'm using the google groups interface. I just noticed teh  
> address is split on Eric's post, but prefectly whole on Ara's. Strange.
> 
> T.
