On Thu, 28 Dec 2006, Pit Capitain wrote:

> Daniel Berger schrieb:
>> I came across a technique for aliasing methods that I have never seen
>> before [1] and was just too good to pass up. (...)
>
> Dan, this is a nice technique indeed (not new, but still nice), but it comes 
> with a performance penalty:
>
>  class HashUsingAlias < Hash
>     alias :old_hset :[]=
>
>     def []=(key, value)
>       self.old_hset(key, value)
>     end
>  end
>
>  class HashUsingBind < Hash
>     hset = self.instance_method(:[]=)
>
>     define_method(:[]=) do |key, value|
>       hset.bind(self).call(key, value)
>     end
>  end
>
>  require "benchmark"
>
>  def bm_report bm, title, hash_class
>    hash = hash_class.new
>    bm.report title do
>      100_000.times do
>        hash[ 1 ] = 1
>      end
>    end
>  end
>
>  Benchmark.bmbm do |bm|
>    bm_report bm, "original", Hash
>    bm_report bm, "alias", HashUsingAlias
>    bm_report bm, "bind", HashUsingBind
>  end
>
> On my system, I get the following results:
>
>                 user     system      total        real
>  original   0.062000   0.000000   0.062000 (  0.062000)
>  alias      0.141000   0.000000   0.141000 (  0.140000)
>  bind       0.656000   0.000000   0.656000 (  0.657000)

mine is slowest of all, however it preserves blocks: see if you can speed it
up:


harp:~ > cat a.rb
class HashUsingAlias < Hash
    alias :old_hset :[]=

    def []=(key, value)
      self.old_hset(key, value)
    end
end

class HashUsingBind < Hash
    hset = self.instance_method(:[]=)

    define_method(:[]=) do |key, value|
      hset.bind(self).call(key, value)
    end
end

require 'override'
class HashUsingOverride < Hash
   override('[]='){ def []=(k,v) super end }
end

require "benchmark"
def bm_report bm, title, hash_class
   hash = hash_class.new
   bm.report title do
     100_000.times do
       hash[ 1 ] = 1
     end
   end
end

Benchmark.bmbm do |bm|
   bm_report bm, "original", Hash
   bm_report bm, "alias", HashUsingAlias
   bm_report bm, "bind", HashUsingBind
   bm_report bm, "override", HashUsingOverride
end



harp:~ > ruby a.rb
Rehearsal --------------------------------------------
original   0.070000   0.000000   0.070000 (  0.070856)
alias      0.140000   0.000000   0.140000 (  0.144095)
bind       0.370000   0.000000   0.370000 (  0.381127)
override   0.470000   0.000000   0.470000 (  0.476067)
----------------------------------- total: 1.050000sec

                user     system      total        real
original   0.070000   0.000000   0.070000 (  0.072046)
alias      0.150000   0.000000   0.150000 (  0.144368)
bind       0.390000   0.000000   0.390000 (  0.388440)
override   0.470000   0.000000   0.470000 (  0.481620)



harp:~ > cat override.rb
class Module
   def child this = self
     @child ||= self.class.new
     @child.module_eval{ include this}
     @child
   end

   def has_child
     defined? @child and @child
   end

   def override m, &b
     this = self

     m = Module.new{
       @m = this.instance_method m
       this.module_eval{ remove_method m rescue nil }

       module_eval <<-code
         def #{ m }(*a, &b)
           um = ObjectSpace._id2ref #{ @m.object_id }
           um.bind(self).call *a, &b
         end
       code

       child.module_eval &b if b
     }

     include(m.has_child ? m.child : m)
   end
end


-a
-- 
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