[#50752] [質問] rescue節で、他パッケージのメッセージ出力を抑止したい — Takahiro Yamaguchi <yamataka@...08.itscom.net>

10 messages 2019/05/02

[ruby-list:50764] 1.next は 1.succ よりなぜ遅い?

From: "5.5" <5.5@...>
Date: 2019-05-29 19:53:55 UTC
List: ruby-list #50764
5.5 と申します。

Integer#succ と Integer#next は同じメソッド(エイリアス)だと
思っていたので,next のほうがかなり遅いということを知って驚き
ました。


require "benchmark_driver"

Benchmark.driver do |r|
   r.report "1.succ"
   r.report "1.next"
   r.report "1 + 1"
end


結果:

               1.succ: 189403887.3 i/s
                1 + 1: 106135608.4 i/s - 1.78x  slower
               1.next:  47203766.8 i/s - 4.01x  slower

$ ruby -v
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]


よく分からないなりに numeric.c の↓ココ

https://github.com/ruby/ruby/blob/b72623012d74abdb06210153ed48c9e2fa075bbd/numeric.c#L3294-L3323

https://github.com/ruby/ruby/blob/b72623012d74abdb06210153ed48c9e2fa075bbd/numeric.c#L5617-L5618

とか見て「やっぱり同じなんでは?」と思ったのですが,

puts RubyVM::InstructionSequence.new("1.next").disasm
# =>
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,6)> (catch: FALSE)
0000 putobject_INT2FIX_1_                                             ( 
  1)[Li]
0001 opt_send_without_block       <callinfo!mid:next, argc:0, 
ARGS_SIMPLE>, <callcache>
0004 leave

puts RubyVM::InstructionSequence.new("1.succ").disasm
# =>
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,6)> (catch: FALSE)
0000 putobject_INT2FIX_1_                                             ( 
  1)[Li]
0001 opt_succ                     <callinfo!mid:succ, argc:0, 
ARGS_SIMPLE>, <callcache>
0004 leave

を見ると,opt_send_without_block と opt_succ の違いに
なっています。

opt_succ って何だろうと,思ったら,るびまの
「YARV Maniacs 【第 9 回】 特化命令」
https://magazine.rubyist.net/articles/0017/0017-YarvManiacs.html
に「特化命令」とありました。


YARV はさっぱり分かりませんが,Integer#succ は Integer#next に
はない最適化がなされている,ということなのでしょうか。

なぜ next には同じ最適化がなされていないのでしょうか。


-- 
5.5@moji.gr.jp

In This Thread

Prev Next