Is the &method(:method_name) idiom bad for performance in Ruby?

Yes, it appears to be bad for performance.

def time
  start = Time.now
  yield
  "%.6f" % (Time.now - start)
end

def do_nothing(arg)
end


RUBY_VERSION # => "1.9.2"

# small
ary = *1..10
time { ary.each(&method(:do_nothing)) }     # => "0.000019"
time { ary.each { |arg| do_nothing arg } }  # => "0.000003"


# large
ary = *1..10_000
time { ary.each(&method(:do_nothing)) }     # => "0.002787"
time { ary.each { |arg| do_nothing arg } }  # => "0.001810"


# huge
ary = *1..10_000_000
time { ary.each(&method(:do_nothing)) }     # => "37.901283"
time { ary.each { |arg| do_nothing arg } }  # => "1.754063"

It looks like this is addressed in JRuby:

$ rvm use jruby
Using /Users/joshuajcheek/.rvm/gems/jruby-1.6.3

$ xmpfilter f.rb 
def time
  start = Time.now
  yield
  "%.6f" % (Time.now - start)
end

def do_nothing(arg)
end


RUBY_VERSION # => "1.8.7"

# small
ary = *1..10
time { ary.each(&method(:do_nothing)) }     # => "0.009000"
time { ary.each { |arg| do_nothing arg } }  # => "0.001000"


# large
ary = *1..10_000
time { ary.each(&method(:do_nothing)) }     # => "0.043000"
time { ary.each { |arg| do_nothing arg } }  # => "0.055000"


# huge
ary = *1..10_000_000
time { ary.each(&method(:do_nothing)) }     # => "0.427000"
time { ary.each { |arg| do_nothing arg } }  # => "0.634000"

Leave a Comment