0
Help us understand the problem. What are the problem?

posted at

updated at

Ruby のエイリアスメソッドはどれを使っても同じ?

Ruby はメソッド名にエイリアス(別名)が多い言語です。
例えば Enumerablemapcollect の二つはエイリアスの関係にあり,どちらを使っても同じ結果になります。
そこで,どちらを使うかは好みの問題となり,「map 派」「collect 派」という言葉まで生まれてしまいました。

では,メソッドに複数の名前があったとき,本当にどれを使っても同じなのでしょうか。
そうとも言い切れない例があります。

Integer には,「レシーバーに 1 足した数を返す」メソッドがあり,nextsucc という二つの名前を持っています。
エイリアスなので機能はもちろん変わらないのですが,速度が違います。

benchmark_driver というベンチマークテスト用 gem をインストールし,

next-succ.yaml
benchmark:
  - 1.next
  - 1.succ

という YAML ファイルを用意して,

benchmark-driver next-succ.yaml

としてみましょう。結果は

       1.succ: 134563685.5 i/s 
       1.next:   8751120.9 i/s - 15.38x  slower

のように,なんと 15 倍もの速度差が出ました。(追記参照のこと)
実験環境:
ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin17]

どうしてこんなことになるかというと,RubyVM 上で succ にだけ何らかの最適化が入っているのだそうです。

では,絶対に next でなく succ を使うべきなのでしょうか。
それは場合によるでしょう。
上の結果を見ると,Integer#next だって毎秒 800 万回以上も実行できるのです。
多数回回るループの中で使うとしても,実用的なコードでは,ループの中の他の処理に比べて遙かに軽いことがほとんどでしょう。
マイクロベンチマークでなく現実のコードで succnext の違いが処理速度を左右することはそう多くはないかもしれません。

追記 2021-11-21

いま改めて同じ方法(マシンは違う)でベンチマークをとってみると,15 倍もの差はなく,2 倍程度でした。Ruby 2.6.3,2.7.4,3.0.2 ともそんな感じです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
0
Help us understand the problem. What are the problem?