-
Notifications
You must be signed in to change notification settings - Fork 369
Expand file tree
/
Copy pathdig-vs-[]-vs-fetch.rb
More file actions
40 lines (32 loc) · 1.05 KB
/
Copy pathdig-vs-[]-vs-fetch.rb
File metadata and controls
40 lines (32 loc) · 1.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
require "benchmark/ips"
HASH = { a: { b: { c: { d: { e: "foo" } } } } }
# Plain Hash#[] is the fastest, but raises NoMethodError when a level is missing.
# Hash#dig returns nil instead, which is why it is the readable choice for nested hashes, at a small cost.
def fastest
HASH[:a][:b][:c][:d][:e]
end
def faster
((((HASH[:a] || {})[:b] || {})[:c] || {})[:d] || {})[:e]
end
def fast
HASH.dig(:a, :b, :c, :d, :e)
end
def slow
HASH.fetch(:a).fetch(:b).fetch(:c).fetch(:d).fetch(:e)
end
# These last two swap places across Rubies; this one is faster on 3.2 and newer.
def slower
HASH[:a] && HASH[:a][:b] && HASH[:a][:b][:c] && HASH[:a][:b][:c][:d] && HASH[:a][:b][:c][:d][:e]
end
def slowest
HASH.fetch(:a, {}).fetch(:b, {}).fetch(:c, {}).fetch(:d, {}).fetch(:e, nil)
end
Benchmark.ips do |x|
x.report("Hash#[]") { fastest }
x.report("Hash#[] ||") { faster }
x.report("Hash#dig") { fast } if RUBY_VERSION >= "2.3.0"
x.report("Hash#fetch") { slow }
x.report("Hash#[] &&") { slower }
x.report("Hash#fetch fallback") { slowest }
x.compare!
end