You can define methods using def
or define_method
. In the real world, there is no performance difference.
define_method
is most often used in metaprogramming, like so:
define_method :"#{attribute_name}_for_realsies?" do
do_things
end
Methods defined via define_method
are usually believed to have worse performance than those defined via def
.
Hence, developers sometimes prefer using class_eval
to define methods using def
, like this:
class_eval "def #{attribute_name}_for_realsies?; do_things; end"
You can benchmark methods defined like this and will see that those defined via def
actually do perform better. Basically, it ranks like this:
-
def
in your class' Ruby code -
def
insideclass_eval
define_method
However, there is only significant difference for really short (or empty) methods. Once you add a bit of logic, all perform almost equally:
require 'benchmark/ips' # requires the 'benchmark-ips' gem
GC.disable
class Foo
define_method("foo") { 10.times.map { "foo".length } }
class_eval 'def bar; 10.times.map { "foo".length }; end'
def baz; 10.times.map { "foo".length }; end
end
Benchmark.ips do |x|
foo = Foo.new
x.report("define_method") { foo.foo }
x.report("def via class_eval") { foo.bar }
x.report("def") { foo.baz }
end
Warming up --------------------------------------
define_method 42.579k i/100ms
class_eval 44.781k i/100ms
def 44.823k i/100ms
Calculating -------------------------------------
define_method 512.248k (± 0.8%) i/s - 2.597M in 5.070730s
def via class_eval 534.132k (± 0.5%) i/s - 2.687M in 5.030474s
def 535.329k (± 0.6%) i/s - 2.689M in 5.023994s
There is a bit more to all that, so I suggest you read the attached article by @tenderlove.
I could confirm his observations on Ruby 2.2 and 2.3, too.
All in all, don't worry about having define_method
for your application's bit of metaprogramming.
It may matter for a framework like Rails, and for methods that are called really often, but that is not your everyday code.
Do keep in mind though that define_method
's closures can prevent objects from being garbage collected.
Update in 2020: Note that, starting with Ruby 2.5, the performance gap between define_method
and def
actually increased a little, to a difference of about 5-10% for the example above (tested for 2.5.7, 2.6.5, 2.7.0). However, the above still applies: for your few lines of meta programming, you won't ever notice any difference. If you want to improve your code's performance, this is not the place to start.