Benchmarking ruby code is essential for improving the performance of applications. The Ruby Standard Library provides a [Benchmark module] (http://ruby-doc.org/stdlib-2.2.0/libdoc/benchmark/rdoc/Benchmark.html) that can be used to measure the running time of any ruby code block.
First, require the Benchmark library:
Benchmark a single block of code
For benchmarking simple blocks of code, use the
The result is in seconds, so instatiating 10 million objects takes a little more than a second. Quite costly!
If we need to print a custom message, we can capture the result and process it:
Compare several blocks
We often need to compare several solutions to a certain problem in order to find out which one is best. Let’s say we want to compare the following two functions for finding the n-th fibonacci number:
The unoptimized recursive version is very slow and will choke on values larger
than 40. Lets use the
#bm method to measure just how much slower it is:
The first argument to
#bm defines the label width and larger values will
shift the results further right. Anyway, we got what we wanted - the recursive
function takes more than a second and a half and the DP version takes a
negligible amount of time. In fact, it can calculate very large fibonacci
numbers in a very little time:
There is another method in the Benchmark library called
#bmbm which runs the
tests twice - the first time to warm up the runtime environment and the second
time to measure the results. You will want to use this method if you worry that
the order of execution of the different code blocks will have an effect on their
The benchmark-ips gem provides even more features than the default Benchmark module. Install it and then require it in your program:
Let’s use it to test our previous functions:
The only difference is the
x.compare! call at the end, but we get a lot more
valuable information about the performance of the two functions - iterations
per second, standard deviation and finally a comparison which shows that the
unoptimized recursive version is more than 100 000 times slower than the DP
There are a few more options available, like setting the time for the warmup and calculation phases or creating a custom suite.
Conclusion and further reading
If you ever wondered if
Enumerable#each was faster than a
for loop or if
.map.flatten is slower than
.flat_map, take a look at the
fast-ruby repo. It contains
answers to those questions and to many others.
The Benchmark module and benchmark-ips gem are really easy to use and provide great information about the performance of your code. They are an essential tool in every developers toolbelt.