Ruby: `&:メソッド名`はブロック変数渡しより若干高速

&:メソッド名はブロック変数渡しより若干高速

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.068287s

Comparison:
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.012293s

Comparison:
Symbol#to_proc: 75242.7 i/s
Block: 66699.0 i/s – 1.13x slower

おまけ

週刊Railsウォッチ(20190107)より。

トリビアですが、&:の間にはスペースがあっても動作は同じです。

[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?)')

おたより発掘

Ruby: `&:メソッド名`はブロック変数渡しより若干高速

これTracePoint( https://docs.ruby-lang.org/ja/latest/class/TracePoint.html )を使って詳細を比較してみると分かる。&:の方が出力されるトレースが少なくてその分速い(って以前纏めた記憶あるけど何処に書いたか忘れた。。

2019/07/15 15:10

関連記事

Mac: Parallels Desktop for MacでUbuntu Server LTS環境を構築する

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の監修および半分程度を翻訳、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れて更新翻訳中。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好きで、Goで書かれたRubyライクなGoby言語のメンテナーでもある。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ

BPSアドベントカレンダー