public
Description: An experiment in publishing code and words about code on a small scale.
Homepage: http://github.com/raganwald/homoiconic/tree/master/homoiconic.markdown
Clone URL: git://github.com/raganwald/homoiconic.git
Click here to lend your support to: homoiconic and make a donation at www.pledgie.com !
homoiconic / 2008-11-07 / comment_on_implementing_advice.markdown
100644 32 lines (24 sloc) 1.664 kb

matthias_georgi commented on reddit:

Looking at the implementation of instance_exec, I am really concerned about performance. This code gets executed for each adviced method call:

def instance_exec(*args, &block)
  begin
    old_critical, Thread.critical = Thread.critical, true
    n = 0
    n += 1 while respond_to?(mname="__instance_exec#{n}")
    InstanceExecHelper.module_eval{ define_method(mname, &block) }
  ensure
    Thread.critical = old_critical
  end
  begin
    ret = send(mname, *args)
  ensure
    InstanceExecHelper.module_eval{ remove_method(mname) } rescue nil
  end
  ret
end

So for each advice call, there will be added an additional method to a module, which will be removed immediately after the call. This approach will probably slow down method calling by factor 10-100 (my estimate).

Well, I know, there isn't any other solution for instance_exec at the moment, but somehow I don't like workarounds in this dimension. However, great article :)

Very correct, and when time permits we could look at a messier but faster solution for Ruby 1.8. I also think this problem goes away in Ruby 1.9.


Subscribe to new posts and daily links:

Reg Braithwaite: Home Page, CV, Twitter