Benchmarking exceptions in Ruby - yep, they're slow.

Just how much slower are exceptions than other flow control mechanisms? In this post we use a simple benchmark to find out.

I've always strongly suspected that exceptions would be slow in ruby compared to other flow control mechanisms. After all - exceptions are a heck of a lot more complicated than a simple "break" or "return." But I've been wrong in my hunches before, so I thought I'd put it to the test.

In the code below I'm using the benchmark-ips gem to compare the relative performance of exiting a loop via exception, break and return. I've seen examples on the web of people doing benchmarks like this with mri 1.9. But I wanted to try it out with mri 2.2.

require 'benchmark/ips'

def exit_via_exception
  5.times do 
    raise RuntimeError
  end
rescue
end

def exit_via_break
  5.times do 
    break
  end
end

def exit_via_return
  5.times do 
    return
  end
end

Benchmark.ips do |x|
  x.report("exception") {  exit_via_exception }
  x.report("break") {  exit_via_break }
  x.report("return") {  exit_via_return }
end

The results are pretty staggering. The function using the exception is less than half as fast as those using break and return.

$ ruby exception_benchmark.rb
Calculating -------------------------------------
           exception    50.872k i/100ms
               break   125.322k i/100ms
              return   124.173k i/100ms
-------------------------------------------------
           exception    714.795k (± 2.7%) i/s -      3.612M
               break      3.459M (± 3.1%) i/s -     17.294M
              return      3.379M (± 3.0%) i/s -     16.888M

This isn't a perfect benchmark

There are a couple of issues that I'm not sure how to compensate for. For example, the exception and break methods have to return. So they're doing more than the method which simply returns. Also I'd be interested to see if rescuing the exception adds to the performance overhead. But not rescuing it causes the benchmark to abort.

Still, exception is so much slower than the other examples that I think the results have meaning even if they're not perfect.

The lesson we learned?

If you're using exceptions as a flow control mechanism. Stop now! Especially if you have a loop consisting of exceptions being raised and caught over and over.

Will this change how I personally use exceptions? Probably not. I can live with a little slowness if the slowness is an exception to the rule. :)

...But what about JRuby and RBx?

Josh Cheek (@josh_cheek on twitter) wrote his own version of this benchmark which is more comprehensive then mine. And he ran it against multiple ruby implementations. You can see his results here. Apparently break is still the winner. :)

What to do next:
  1. Try Honeybadger for FREE
    Honeybadger helps you find and fix errors before your users can even report them. Get set up in minutes and check monitoring off your to-do list.
    Start free trial
    Easy 5-minute setup — No credit card required
  2. Get the Honeybadger newsletter
    Each month we share news, best practices, and stories from the DevOps & monitoring community—exclusively for developers like you.
    author photo

    Starr Horne

    Starr Horne is a Rubyist and Chief JavaScripter at Honeybadger.io. When she's not neck-deep in other people's bugs, she enjoys making furniture with traditional hand-tools, reading history and brewing beer in her garage in Seattle.

    More articles by Starr Horne
    Stop wasting time manually checking logs for errors!

    Try the only application health monitoring tool that allows you to track application errors, uptime, and cron jobs in one simple platform.

    • Know when critical errors occur, and which customers are affected.
    • Respond instantly when your systems go down.
    • Improve the health of your systems over time.
    • Fix problems before your customers can report them!

    As developers ourselves, we hated wasting time tracking down errors—so we built the system we always wanted.

    Honeybadger tracks everything you need and nothing you don't, creating one simple solution to keep your application running and error free so you can do what you do best—release new code. Try it free and see for yourself.

    Start free trial
    Simple 5-minute setup — No credit card required

    Learn more

    "We've looked at a lot of error management systems. Honeybadger is head and shoulders above the rest and somehow gets better with every new release."
    — Michael Smith, Cofounder & CTO of YvesBlue

    Honeybadger is trusted by top companies like: