Performance implications of procs and blocks in Ruby

[tweetmeme]
Whilst profiling the performance of some code, I wondered why a method that was yielding to a small block of code was taking so long.

The answer was in the method arguments where out of habit I automatically capture the block argument and convert it to a proc using the ampersand (&) operator. When yielding to code that you are passing to a method, there is no need to convert the block to a proc as the block of code that you are yielding to is already a proc in the correct context.

An example to clarify:

# if you just want to yield to code, this way is inefficient
# as the block argument will be converted to a proc
def foo(argument, &block)
  if some_logic
    block.call  # if we are just yielding to the block in the
                  # context it is already in, this is unnecessary.
  end
end

# if you are just yielding to code, this way is better
def bar(argument)
  if some_logic
    yield  # much better, there was no overhead
            # of converting the block into a proc
  end
end

# called like so
bar(my_argument) { p "Hello" }

Blocks and procs are complicated, here are a couple of resources:

Posted in Ruby. Tags: , , . 1 Comment »