加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 为什么`-1 * x`比`-x`快?为什么?

发布时间:2020-12-16 19:22:40 所属栏目:百科 来源:网络整理
导读:使用此代码: include Benchmarkn = 10**8r = []Benchmark.benchmark(" "*7 + CAPTION,7,FORMAT,"avg:","total:") do |b| a = 1 r b.report("Benchmark -1:") { (n).times do -1 * a end } r b.report("Benchmark - :") { (n).times do -a end } [(r.sum{|e|
使用此代码:
include Benchmark
n = 10**8
r = []
Benchmark.benchmark(" "*7 + CAPTION,7,FORMAT,">avg:",">total:") do |b|
  a = 1

  r << b.report("Benchmark -1:")   { (n).times do
    -1 * a
  end }

  r << b.report("Benchmark - :")   { (n).times do
    -a
  end }

  [(r.sum{|e| e }) / 2,r.sum{|e| e }]
end

我在ruby 2.1.5p273(2014-11-13修订版48405)[x86_64-linux]上得到了这个结果:

user     system      total        real
Benchmark -1:  4.930000   0.000000   4.930000 (  4.938359)
Benchmark - :  5.650000   0.000000   5.650000 (  5.667566)
>avg:     5.290000   0.000000   5.290000 (  5.302962)
>total:  10.580000   0.000000  10.580000 ( 10.605924)

这看起来很直观,因为如果我猜我会打赌“-x”而不是“-1 * x”更快.

为什么不同?或者我的测量中存在一些重大缺陷?

解决方法

如果查看生成的字节码,它可能会有所帮助.如果你将它简化为简单的东西
puts RubyVM::InstructionSequence.compile(<<-CODE
a = 1
-1 * a
CODE
).to_a.join("n")


puts RubyVM::InstructionSequence.compile(<<-CODE
a = 1
-a
CODE
).to_a.join("n")

您还可以使用#?$ruby?? –dump insns -e’code’来打印指令序列(如@Stefan所述),这将实际输出更清晰的输出.

#~$ruby --dump insns -e 'a = 1; -a'
== disasm: <RubyVM::InstructionSequence:<main>@-e>======================
local table (size: 2,argc: 0 [opts: 0,rest: -1,post: 0,block: -1] s1)
[ 2] a          
0000 trace            1                                               (   1)
0002 putobject        1
0004 setdynamic       a,0
0007 trace            1
0009 getdynamic       a,0
0012 send             :-@,nil,<ic:0>
0018 leave            
#~$ruby --dump insns -e 'a = 1; -1 * a'
== disasm: <RubyVM::InstructionSequence:<main>@-e>======================
local table (size: 2,0
0007 trace            1
0009 putobject        -1
0011 getdynamic       a,0
0014 opt_mult         <ic:1>
0016 leave

你会注意到在字节码列表中,在-1 *中,Ruby做了一个opt_mult,它基本上只是一个算术运算,并在内部进行了优化.另一方面,-a位是opt_send_without_block,它是实际的方法调用.我的猜测是这就是为什么第二个版本(有点)慢了.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读