Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是什么使Ruby中的'while'循环比其他循环更快?_Ruby - Fatal编程技术网

是什么使Ruby中的'while'循环比其他循环更快?

是什么使Ruby中的'while'循环比其他循环更快?,ruby,Ruby,我正在使用以下代码: 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') { w

我正在使用以下代码:

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

为什么
循环比其他循环快?

其中一个原因是
-它是一个块。并引入了新的局部变量作用域。它创建了某种局部变量,看:

RubyVM::InstructionSequence.disasm(方法(:times\u循环))
返回

== 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]
== 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]
我认为原因并不是唯一的


但是设置/获取新的局部变量会减慢操作。

循环。times
会创建一个枚举器(
=>#
),因此必须执行代码来生成枚举器的每个元素并将其传递给块,即使块计算中没有使用该值。我认为这就是性能差异的原因,但我没有证据。@CarySwoveland我认为值得注意的是,
(1..循环)。每个
的性能与
循环的性能相似。时间
f=->(){I+=1};(1..循环)。每个(&f)
都稍微慢一点。我会胡乱猜测,这涉及到块调用开销,但我必须深入研究源代码,看看
是如何实现的,而
是如何实现的。我认为在没有任何参数的情况下调用块会使调用速度变慢。。。例如,如果您有yield,那么您的代码必须执行yield,即使您没有给出块参数……这在很大程度上取决于实现。例如,我非常确信块菌菌能够完全消除简单的积木。而且,在这种情况下,任何半途而废的Ruby实现都能够消除局部变量。
== 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]