オブジェクトに存在するメソッドを呼び出すケース・nil
に対して呼び出すケースをそれぞれ比較。
safe.rb
require 'benchmark'
require 'active_support/all'
N = 10_000_000
class Foo
def foo
end
end
foo = Foo.new
bar = nil
Benchmark.bm do |b|
b.report('Object&. ') do
N.times { foo&.foo }
end
b.report('Object#try ') do
N.times { foo.try(:foo) }
end
b.report('Object#try! ') do
N.times { foo.try!(:foo) }
end
b.report('NilClass&. ') do
N.times { bar&.foo }
end
b.report('NilClass#try ') do
N.times { bar.try(:foo) }
end
b.report('NilClass#try!') do
N.times { bar.try!(:foo) }
end
end
$ ruby safe.rb
user system total real
Object&. 0.610000 0.000000 0.610000 ( 0.612233)
Object#try 3.440000 0.000000 3.440000 ( 3.454373)
Object#try! 2.710000 0.010000 2.720000 ( 2.720780)
NilClass&. 0.450000 0.000000 0.450000 ( 0.446206)
NilClass#try 1.360000 0.000000 1.360000 ( 1.375241)
NilClass#try! 1.370000 0.010000 1.380000 ( 1.368077)
Safe Navigation Operator は try
や try!
よりかなり速いことがわかりました。
なので Ruby 2.3 以降を使っているのであれば、積極的に置き換えて行くのが良さそうですね。
なお、Safe Navigation Operator は try!
相当の挙動なので、オブジェクトに対して存在しないメソッドを呼ぼうとすると NoMethodError
が発生します。