Your Code Is Slow - How to Find It

benchmark, performance, rails, ruby

You’ve checked your server logs. You looked up New Relic. And you just confirmed it – that last change you pushed to prod is slower than a turtle. You think you know what the problem is but you’re not sure. You make a hasty change and deploy it. But the code is still slow – you guessed wrong!

What if you could avoid guess and check performance testing? What if you could hone in on slow code and fix it once, without having to guess and make changes that don’t work?

The way to get there is easy – use the Benchmark class. Benchmark is a built in Ruby class that allows you to wrap your code and measure how long it takes to execute. Here’s a simple example:

1
2
3
4
5
6
7
8
9
10
11
def show
  puts Benchmark.measure {
    method_1()
  }
  puts Benchmark.measure {
    method_2()
  }
  puts Benchmark.measure {
    method_3()
  }
end

Above each method call is wrapped with the measure method and it’s going to print out the results of the work done:

1
2
3
4
5
6
7
8
#   user     system      total        real
0.010000   0.010000   0.020000 (  0.035638)

#   user     system      total        real
0.359740   0.010000   0.369740 (  0.370056)

#   user     system      total        real
0.004000   0.010997   0.014997 (  0.015228)

Those results (which are measured in seconds) are going to tell you 1 of 3 things:

  1. If the code is fast
  2. If the code is slow
  3. Which part of your code is slow

In the above example you’d want to dig into method_2 since that’s the most expensive method call being made (370 ms).

Let’s break down what user, system, total, and real mean so that you can further diagnose performance issues in your code:

  • user: is time spent in user-mode. This is going to be code you write or incorporate into your project.
  • system: is time where the kernel is making system calls on your program’s behalf. An example would be file I/O code.
  • total: is the sum of user and system time.
  • real: is how long the code takes to run against wall clock time.

With those definitions in mind, if you benchmark a method and user time is high, then it’s either your code, framework code (like Rails), or a gem that’s causing the slow down.

If on the other hand you saw a large amount of time under system then hone in on places where you’re making system calls (like reading or writing a file.)

And if you saw a spike in real, but no change in user and system … then you probably just have a sleep call somewhere in your code ;)

Benchmarking Code in Console

The other place where Benchmark can come in handy is during initial development of a method. Often I’ll write 2 different methods and Benchmark both to see which one performs better. If there’s a significant difference I’ll use the more performant code. If there is minimal or no difference at all, I’ll use the easiest to understand code.

One thing you’ll want to do when console benchmarking is run your code multiple times. What I like to do is run a Benchmark 5 times, discard the min and max times, and then average the remaining 3 results. By doing that I see consistent timings for the method.

I hate to sound like your mom, but if you’re not using Benchmark regularly to find what’s slowing your app down, you should be! The Benchmark docs provide other methods you can use, but honestly you’ll rarely need anything more than measure. When push comes to shove it’s the best way to quickly identify where a performance problem is occurring so that you can start fixing it!

If you want to receive regular tips on improving Rails performance add your name in the below box:

I will not sell your email address, you can unsubscribe at anytime, and I am not an affiliate for anything. In the event that I build or make something related to this blog, I'll send you discounts, early access, and freebies!

This page was delicately crafted on by .