Today I learned in Rubyland
Benchmarking my Ruby code shed light on a few things I didnβt know before about .nil?
and Set#include?
.
Boolean operations nil?
vs ==
.nil?
makes the code more readable, but itβs slowing things down.
require 'benchmark'
n = 1_000_000
Benchmark.bm do |x|
x.report('nil?') { n.times { nil.nil? } }
x.report('==') { n.times { nil == nil } }
end
[#<Benchmark::Tms:0x000000011ee2b1d8
@cstime=0.0,
@cutime=0.0,
@label="nil?",
@real=0.046839999999065185,
@stime=0.0005310000000000037,
@total=0.046846,
@utime=0.046314999999999995>,
#<Benchmark::Tms:0x000000011ee2b098
@cstime=0.0,
@cutime=0.0,
@label="==",
@real=0.033373000000210595,
@stime=0.00028000000000000247,
@total=0.033374000000000015, πππ
@utime=0.03309400000000001>]
Take a look at this:
require 'benchmark'
h = {a: 1, b: {c: 2}}
n = 1_000_000
Benchmark.bm do |x|
x.report('nil?') { n.times { h.dig(:b, :d).nil? } }
x.report('==') { n.times { h.dig(:b, :d) == nil } }
end
[#<Benchmark::Tms:0x0000000122c0aaa8
@cstime=0.0,
@cutime=0.0,
@label="nil?",
@real=0.09058699999877717,
@stime=0.0007450000000000095,
@total=0.09056200000000002,
@utime=0.08981700000000001>,
#<Benchmark::Tms:0x0000000122c0a968
@cstime=0.0,
@cutime=0.0,
@label="==",
@real=0.07575299999734852,
@stime=0.0001769999999999966,
@total=0.075752, πππ
@utime=0.075575>]
Rubyβs Set
class performance
The performance of the Set
class, can be worse than building a hash lookup table in some cases.
Take a look at this:
require 'benchmark'
s_array = Set[[1, 2], [3, 4], [5, 6]]
s_hash = Set[{x: 1, y: 2}, {x: 3, y: 4}, {x: 5, y: 6}]
s_string = Set['1_2', '3_4', '5_6']
h = {1 => {2 => true}, 3 => {4 => true}, 5 => {6 => true}}
n = 1_000_000
Benchmark.bm do |x|
x.report('Set#include? Array') { n.times { s_array.include?([1, 2]) } }
x.report('Set#include? Hash') { n.times { s_hash.include?({x: 1, y: 2}) } }
x.report('Set#include? String') { n.times { s_string.include?("1_2") } }
x.report('[]') { n.times { h.dig(1, 2) } }
end
[#<Benchmark::Tms:0x000000011ee4ff60
@cstime=0.0,
@cutime=0.0,
@label="Set#include? Array",
@real=0.3224740000005113,
@stime=0.0011849999999999916,
@total=0.3223769999999999,
@utime=0.3211919999999999>,
#<Benchmark::Tms:0x000000011ee4fd30
@cstime=0.0,
@cutime=0.0,
@label="Set#include? Hash",
@real=0.4202399999994668,
@stime=0.0027610000000000134,
@total=0.4201859999999997,
@utime=0.4174249999999997>,
#<Benchmark::Tms:0x000000011ee4fbf0
@cstime=0.0,
@cutime=0.0,
@label="Set#include? String",
@real=0.08109800000238465,
@stime=0.0010399999999999299,
@total=0.0810949999999997, πππ
@utime=0.08005499999999977>,
#<Benchmark::Tms:0x000000011ee4fa60
@cstime=0.0,
@cutime=0.0,
@label="[]",
@real=0.0856240000030084,
@stime=0.0006800000000000139,
@total=0.08562099999999973, π
@utime=0.08494099999999971>]
Depending on the use case, it might be better to use a hash lookup table instead of a Set
.
If youβre working with strings, the Set
class is the best choice!
Read next β‘οΈ