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

def exit_via_break
  5.times do 

def exit_via_return
  5.times do 

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

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. Sign up for a FREE Honeybadger account
    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.
    Get started free
  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 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
    “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
    Try Honeybadger Free for 15 Days