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,它是实际的方法调用.我的猜测是这就是为什么第二个版本(有点)慢了. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |