为什么proc可能比块运行得更快?

时间:2012-07-14 02:06:52

标签: ruby internals

另一个问题

This answer

array.map(&:to_s)

array.map { |n| n.to_s }

在第一个示例中,&:to_s变为Proc。第二个例子使用一个块。

为什么Proc比基准测试中的块更快?这种技术是否允许解释器进行一些优化?

3 个答案:

答案 0 :(得分:5)

这不是关于“proc vs block”。

这是一个简单的实验(随意复制和运行):

require 'benchmark'

many = 500
array = (1..10000).to_a

proc = proc { |a| a.to_s }

Benchmark.bm do |x|
  x.report('Symbol#to_proc') { many.times { array.map(&:to_s) } }
  x.report('proc') { many.times { array.map(&proc) }  }
  x.report('block') { many.times { array.map { |a| a.to_s } }  }
end

Ruby 1.9.3p194结果:

                user     system      total        real
Symbol#to_proc  1.170000   0.000000   1.170000 (  1.169055)
proc            1.450000   0.000000   1.450000 (  1.454216)
block           1.450000   0.000000   1.450000 (  1.448094)

如您所见,blockproc几乎占用了相同的CPU时间。神奇的是Symbol#to_proc本身。

答案 1 :(得分:4)

正如其他人所说的那样,这是一般性的Symbol#to_proc,而不是一般的过程,而且几乎可以肯定是ruby实现依赖。在Symbol#to_proc本身处于ruby本身之前,它的纯ruby实现肯定比等效块慢。

要获得真正的答案,您需要在执行此类基准测试时对ruby进行分析。

我对ruby源代码的阅读是,当你调用Symbol#to_proc时,你得到的proc有点特别:proc的主体只是一个C api调用(rb_funcall_passing_block),而在在其他情况下,它是实际的ruby代码,需要更长的时间才能执行。

答案 2 :(得分:0)

只是一个猜测,但也许是因为Proc不需要以与块相同的方式保持调用的上下文。块需要知道在它之外声明的变量,Proc不会。