visit
Benchmarking is the process of measuring the performance of something.And that's it, there is nothing more to add.Yeah, I know what you're thinking, that knowing the meaning doesn't serve your purpose. But I'm positive that at least it will give you a broad idea.
Benchmarking gives you knowledge, and knowledge is power.
Benchmarking gives you a simple view of how your code is performing. This view focuses on three main areas: elapsed time, memory, and iterations per second.
a. The first step is to install this in your system; for that, you can use this command:
gem install benchmark-ips benchmark-memory
b. The second step is creating a ruby file, I'm going to call it "benchmarking_ruby.rb", but you can name it in any way you want:
touch benchmarking_ruby.rb
b.1 Open the file with your preferred text editor. This file will contain three main sections:
- Section 1: Here we use to include and grant our file access to the gems recently installed and the Ruby Benchmark Class. Doing so, will allow us to use the benchmark methods to measure our code performance.
require 'benchmark'
require 'benchmark/memory'
require 'benchmark/ips'
- Section 2: We write the code that we want to benchmark.
def method_1(params)
# some code
end
def method_2(params)
# some code
end
Note: Benchmark works if you want to measure a single method but it's best if you test at least two or more. Don't worry too much about this right now, later on, I'll show you an example and you'll understand what I meant.
- Section 3: We set up the test.
This part is tricky but not complicated. Look at the image below and try to identify what's happening.def benchmark(params)
Benchmark.bmbm do |x|
x.report ("Method One") { method_1(params) }
x.report ("Method Two") { method_2(params) }
end
Benchmark.memory do |x|
x.report ("Method One") { method_1(params) }
x.report ("Method Two") { method_2(params) }
x.compare!
end
Benchmark.ips do |x|
x.report ("Method One") { method_1(params) }
x.report ("Method Two") { method_2(params) }
x.compare!
end
end
benchmark(params)
We are declaring a method called "benchmark" that accepts some parameters (or arguments).
def benchmark(params)
...
end
def benchmark(params)
Benchmark.bmbm do |x|
# ::bmbm will measure the "ELAPSED TIME"
end
Benchmark.memory do |x|
# ::memory will measure the "ALLOCATED MEMORY"
end
Benchmark.ips do |x|
# ::ips will measure "ITERATIONS PER SECOND"
end
end
Notice the comments inside each block?
The inner part of each block contains a report method that accepts a string and also a block. The string acts as a short description, and in the block, we call the methods we wrote in Section 2.
...
Benchmark.bmbm do |x|
x.report ("description or identifier") { # method call }
end
...
...
Benchmark.memory do |x|
x.report ("Method One") { method_1(params) }
x.report ("Method Two") { method_2(params) }
x.compare!
end
...
The last bit in our file is just the call for the "benchmark" method.
benchmark(params)
c) And last but not least, The third step is to save your changes and run the ruby script you have created.
ruby bencharking_ruby.rb
# You're given an array with n elements inside it.
# Your task is to print the sum fo all elements in
# the most efficient way possible.
# Input
[*(0..1_000_000)] # ordered array of one million elements.
# Output
500_000_500_000
# Solution 1: sum all elements using a "while loop".
def sum_1(arr)
sum = 0
i = 0
while i < arr.size
sum += arr[i]
i += 1
end
sum
end
# Solution 2: sum all elements using the "each" method.
def sum_2(arr)
sum = 0
arr.each do |num|
sum += num
end
sum
end
# Solution 3: sum all elements using the "sum" method.
def sum_3(arr)
arr.sum
end
# Solution 4: sum all elements using the "inject" method.
def sum_4(arr)
arr.inject(&:+)
end
At this time you remember that you learn to benchmark your code by reading a random article in hackernoon and you set up your benchmarking environment.
You create your file.touch sum_array_elements.rb
require "benchmark"
require "benchmark-memory"
require "benchmark/ips"
def sum_1(arr)
sum = 0
i = 0
while i < arr.size
sum += arr[i]
i += 1
end
sum
end
def sum_2(arr)
sum = 0
arr.each do |num|
sum += num
end
sum
end
def sum_3(arr)
arr.sum
end
def sum_4(arr)
arr.inject(&:+)
end
def benchmark(arr)
puts "--- Elapsed Time ----------------------"
Benchmark.bmbm do |x|
x.report ("while loop") { sum_1(arr) }
x.report ("#each") { sum_2(arr) }
x.report ("#sum") { sum_3(arr) }
x.report ("#inject") { sum_4(arr) }
end
puts "--- Memory ----------------------------"
Benchmark.memory do |x|
x.report ("while loop") { sum_1(arr) }
x.report ("#each") { sum_2(arr) }
x.report ("#sum") { sum_3(arr) }
x.report ("#inject") { sum_4(arr) }
x.compare!
end
puts "--- Iterations per Second -------------"
Benchmark.ips do |x|
x.report ("while loop") { sum_1(arr) }
x.report ("#each") { sum_2(arr) }
x.report ("#sum") { sum_3(arr) }
x.report ("#inject") { sum_4(arr) }
x.compare!
end
end
arr = [*(0..1_000_000)]
benchmark(arr)
ruby sum_array_elements.rb
--- Elapsed Time ---------------------------------------
Rehearsal ----------------------------------------------
while loop 0.066358 0.000000 0.066358 ( 0.069475)
#each 0.068786 0.000000 0.068786 ( 0.070810)
#sum 0.001983 0.000000 0.001983 ( 0.002005)
#inject 0.158601 0.000956 0.159557 ( 0.163468)
------------------------------------- total: 0.296684sec
user system total real
while loop 0.056899 0.000016 0.056915 ( 0.058878)
#each 0.082691 0.000000 0.082691 ( 0.085142)
#sum 0.002014 0.000000 0.002014 ( 0.002128)
#inject 0.156500 0.001905 0.158405 ( 0.163096)
--- Memory ---------------------------------------------
Calculating -------------------------------------
while loop 0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
#each 0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
#sum 0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
#inject 0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
Comparison:
while loop: 0 allocated
#each: 0 allocated - same
#sum: 0 allocated - same
--- Iterations per Second ------------------------------
Warming up --------------------------------------
while loop 1.000 i/100ms
#each 1.000 i/100ms
#sum 42.000 i/100ms
#inject 1.000 i/100ms
Calculating -------------------------------------
while loop 19.848 (±10.1%) i/s - 99.000 in 5.021740s
#each 14.161 (± 7.1%) i/s - 71.000 in 5.037058s
#sum 430.010 (± 5.1%) i/s - 2.184k in 5.092623s
#inject 6.405 (±15.6%) i/s - 32.000 in 5.031657s
Comparison:
#sum: 430.0 i/s
while loop: 19.8 i/s - 21.66x (± 0.00) slower
#each: 14.2 i/s - 30.37x (± 0.00) slower
#inject: 6.4 i/s - 67.13x (± 0.00) slower
--- Elapsed Time ---------------------------------------
Rehearsal ----------------------------------------------
while loop 0.066358 0.000000 0.066358 ( 0.069475)
#each 0.068786 0.000000 0.068786 ( 0.070810)
#sum 0.001983 0.000000 0.001983 ( 0.002005)
#inject 0.158601 0.000956 0.159557 ( 0.163468)
------------------------------------- total: 0.296684sec
user system total real
while loop 0.056899 0.000016 0.056915 ( 0.058878)
#each 0.082691 0.000000 0.082691 ( 0.085142)
#sum 0.002014 0.000000 0.002014 ( 0.002128)
#inject 0.156500 0.001905 0.158405 ( 0.163096)
--- Memory ----------------------------------------
Calculating -------------------------------------
while loop 0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
#each 0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
#sum 0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
#inject 0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
Comparison:
while loop: 0 allocated
#each: 0 allocated - same
#sum: 0 allocated - same
#inject: 0 allocated - same
In this case, it's a tie. Every method seems efficient, none of them is using space in your hard drive. We can tell by looking at the "Comparison" section.
At this point, every method still has a chance of proving that if they are the best solution to the problem.So we analyze the last part.--- Iterations per Second ------------------------------
Warming up --------------------------------------
while loop 1.000 i/100ms
#each 1.000 i/100ms
#sum 42.000 i/100ms
#inject 1.000 i/100ms
Calculating -------------------------------------
while loop 19.848 (±10.1%) i/s - 99.000 in 5.021740s
#each 14.161 (± 7.1%) i/s - 71.000 in 5.037058s
#sum 430.010 (± 5.1%) i/s - 2.184k in 5.092623s
#inject 6.405 (±15.6%) i/s - 32.000 in 5.031657s
Comparison:
#sum: 430.0 i/s
while loop: 19.8 i/s - 21.66x (± 0.00) slower
#each: 14.2 i/s - 30.37x (± 0.00) slower
#inject: 6.4 i/s - 67.13x (± 0.00) slower