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
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
Those results (which are measured in seconds) are going to tell you 1 of 3 things:
- If the code is fast
- If the code is slow
- 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
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
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!