我正在使用以下代码:
require 'benchmark'
LOOPS = 100_000_000
def while_loop
i = 0
while i < LOOPS do i += 1 end
end
def times_loop
i = 0
LOOPS.times { i += 1 }
end
Benchmark.benchmark do |b|
b.report('while') { while_loop }
b.report('times') { times_loop }
end
输出为(Ruby 2.6.0):
while 2.419529 0.000000 2.419529 ( 2.426470)
times 7.225500 0.005673 7.231173 ( 7.252794)
为什么while
的循环速度比其他人快?
答案 0 :(得分:4)
原因之一是因为times
-这是一个障碍。并且引入了新的局部变量作用域。并创建某种局部变量,如下所示:
RubyVM::InstructionSequence.disasm(method(:times_loop))
返回
== disasm: #<ISeq:times_loop@1.rb:23 (23,0)-(26,3)>=====================
== catch table
| catch type: break st: 0003 ed: 0014 sp: 0000 cont: 0014
== disasm: #<ISeq:block in times_loop@1.rb:25 (25,14)-(25,24)>==========
== catch table
| catch type: redo st: 0001 ed: 0010 sp: 0000 cont: 0001
| catch type: next st: 0001 ed: 0010 sp: 0000 cont: 0010
|------------------------------------------------------------------------
0000 nop ( 25)[Bc]
0001 getlocal_OP__WC__1 i[Li]
0003 putobject_OP_INT2FIX_O_1_C_
0004 opt_plus <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <callcache>
0007 dup
0008 setlocal_OP__WC__1 i
0010 leave [Br]
|------------------------------------------------------------------------
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] i
0000 putobject_OP_INT2FIX_O_0_C_ ( 24)[LiCa]
0001 setlocal_OP__WC__0 i
0003 getinlinecache 10, <is:0> ( 25)[Li]
0006 getconstant :LOOPS
0008 setinlinecache <is:0>
0010 send <callinfo!mid:times, argc:0>, <callcache>, block in times_loop
0014 leave ( 26)[Re]
在这种情况下,有两个局部变量(setlocal_OP__WC__1
和setlocal_OP__WC__0
)。
相反的while
仅使用一个,RubyVM::InstructionSequence.disasm(method(:while_loop))
返回
== disasm: #<ISeq:while_loop@1.rb:15 (15,0)-(20,3)>=====================
== catch table
| catch type: break st: 0009 ed: 0032 sp: 0000 cont: 0032
| catch type: next st: 0009 ed: 0032 sp: 0000 cont: 0006
| catch type: redo st: 0009 ed: 0032 sp: 0000 cont: 0009
|------------------------------------------------------------------------
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] i
0000 putobject_OP_INT2FIX_O_0_C_ ( 16)[LiCa]
0001 setlocal_OP__WC__0 i
0003 jump 17 ( 17)[Li]
0005 putnil
0006 pop
0007 jump 17
0009 getlocal_OP__WC__0 i ( 18)[Li]
0011 putobject_OP_INT2FIX_O_1_C_
0012 opt_plus <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <callcache>
0015 setlocal_OP__WC__0 i
0017 getlocal_OP__WC__0 i ( 17)
0019 getinlinecache 26, <is:0>
0022 getconstant :LOOPS
0024 setinlinecache <is:0>
0026 opt_lt <callinfo!mid:<, argc:1, ARGS_SIMPLE>, <callcache>
0029 branchif 9
0031 putnil
0032 leave ( 20)[Re]
我认为原因不是唯一的原因。
但是设置/获取新的本地变量会减慢操作速度。