&:メソッド名
はブロック変数渡しより若干高速
Use fast ruby idioms by oniofchaos · Pull Request #32337 · rails/railsのしょっぱなに、ブロック変数を用いるブロック渡しより、&:メソッド名
渡しの方が高速だと説明されています。
require 'benchmark/ips'
RANGE = (1..100)
def slow
RANGE.map { |i| i.to_s }
end
def fast
RANGE.map(&:to_s)
end
Benchmark.ips do |x|
x.report('Block') { slow }
x.report('Symbol#to_proc') { fast }
x.compare!
end
Ubuntu 18.4.2 LTS(macOS環境のParallels DesktopのVM上)のRuby 2.6.3で実行してみると、誤差の範囲とはいえ、&:メソッド名
の方がわずかに高速です。なお、実行にはgem install benchmark-ips
をやっておく必要があります。
ruby block-vs-to_proc.rb
Warming up ————————————–
Block 7.317k i/100ms
Symbol#to_proc 8.042k i/100ms
Calculating ————————————-
Block 70.244k (± 6.8%) i/s – 351.216k in 5.026038s
Symbol#to_proc 76.526k (± 6.5%) i/s – 386.016k in 5.068287sComparison:
Symbol#to_proc: 76525.7 i/s
Block: 70243.9 i/s – same-ish: difference falls within error
なお、macOS Mojave環境のRuby 2.6.3だともう少し差が開きました。いずれも数回回してみましたが、参考値ということで。
ruby block-vs-to_proc.rb
Warming up ————————————–
Block 6.854k i/100ms
Symbol#to_proc 6.607k i/100ms
Calculating ————————————-
Block 66.699k (± 8.0%) i/s – 335.846k in 5.077837s
Symbol#to_proc 75.243k (± 3.6%) i/s – 376.599k in 5.012293sComparison:
Symbol#to_proc: 75242.7 i/s
Block: 66699.0 i/s – 1.13x slower
おまけ
トリビアですが、&
と:
の間にはスペースがあっても動作は同じです。
[1, 2, 3].select(&:even?)
[1, 2, 3].select(& :even?)
RubyのRipperなどでパーサーの動きを確認できます。
require 'ripper'
Ripper.sexp('[1, 2, 3].select(&:even?)')
Ripper.sexp('[1, 2, 3].select(& :even?)')