Ruby Benchmarking Intro

Merdan Durdiyev
kode-art
Published in
3 min readJul 18, 2023

Introduction

Welcome back, dear readers, coders, enthusiasts, and Rubyists.

Hope you’re all doing fine. And we are back with one more article about Ruby. Specifically about benchmarking the Ruby code.

Ruby’s Benchmark module provides methods to measure and report the time used to execute Ruby code.

The report provides data about the user CPU time, system CPU time, the sum of the user and system CPU times, and the elapsed real time. The unit of time is seconds. So let’s take a look about measuring the time required to perform a single block of code and compare performance of several blocks of code in next chapters.

Measuring a Single block of code

Just as a simple intro to measuring performance, let’s measure the time to construct a string given by the expression "a"*1_000_000_000, i.e. billion length string.

require 'benchmark'

puts Benchmark.measure { "a"*1_000_000_000 }

On my machine (MSI GF63) it gives out this report:

0.080000   0.190000   0.270000 (  0.269540)

Depending on the machine and its specifications, you could get different results.

Measuring Multiple blocks of code

Previous part was about measuring single block of code. But what about measuring several blocks of code, say, to compare their performance times.

To measure several blocks of code, we need to use ‘bm’ method and pass several blocks to ‘report’ method in it. To make things easier, I copy pasted several sorting algorithms from Rubyalgo website, that I truly recommend. For this example we can use 3 sorting algorithms: Quicksort, Bubblesort, and Mergesort. I copied these algorithms into ‘sorting_algorithms.rb’ file and included that file in our benchmarking file.

As an input, we created an array of 100_000 random numbers. This is an example where we compare several sorting algorithms using the same input array :

require 'benchmark'
require './sorting_algorithms'

input_array = Array.new(100_000) { rand(1...9) }

Benchmark.bm do |blk|
blk.report { ArraySorter.quick_sort(input_array, 0, input_array.length-1) }
blk.report { ArraySorter.bubble_sort(input_array) }
blk.report { ArraySorter.merge_sort(input_array, 0, input_array.length-1) }
end

These blocks, print out the following report:

       user     system      total        real
0.070000 0.000000 0.070000 ( 0.064320)
0.000000 0.000000 0.000000 ( 0.003097)
0.190000 0.000000 0.190000 ( 0.188274)

Besides that, we can label each of the blocks, so that we can apparently see which report belongs to which block of code at a first glance. To label a block of code we need to pass a label name to ‘report’ method. You can optionally pass a label width to ‘bm’ method. In our example, we’re setting the width to 10 characters.

require 'benchmark'
require './sorting_algorithms'

input_array = Array.new(100_000) { rand(1...9) }

Benchmark.bm(10) do |blk|
blk.report("Quick sort") { ArraySorter.quick_sort(input_array, 0, input_array.length-1) }
blk.report("Bubble sort") { ArraySorter.bubble_sort(input_array) }
blk.report("Merge sort") { ArraySorter.merge_sort(input_array, 0, input_array.length-1) }
end

This time we get a labelled report, and clearly see the performance for each algorithm:

                 user     system      total        real
Quick sort 0.070000 0.000000 0.070000 ( 0.064386)
Bubble sort 0.000000 0.000000 0.000000 ( 0.003193)
Merge sort 0.190000 0.000000 0.190000 ( 0.187733)

Conclusion

There were times I was wondering which way to use for solving a specific problem. Either one with shorter code, or the other, one provided by a library, or one I developed myself. Now I have a proper way and a tool to differentiate them. I hope you will also find this helpful and use it when you’re stuck selecting either of the choices.

You can find the useful resources used in this article down below.

Wish you tons of motivation to go further and open new doors, conquer new horizons.

--

--