Posted over 3 years ago. Visible to the public. Linked content.

There is no real performance difference between "def" and "define_method"

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:

Copy
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:

Copy
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:

  1. def in your class' Ruby code
  2. def inside class_eval
  3. 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:

Copy
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
Copy
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.

Growing Rails Applications in Practice
Check out our new e-book:
Learn to structure large Ruby on Rails codebases with the tools you already know and love.

Owner of this card:

Avatar
Arne Hartherz
Last edit:
2 months ago
by Arne Hartherz
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Arne Hartherz to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more