另一个问题的答案说明了这一点
array.map(&:to_s)
Run Code Online (Sandbox Code Playgroud)
比...更快
array.map { |n| n.to_s }
Run Code Online (Sandbox Code Playgroud)
在第一个例子中,&变成:to_s了Proc.第二个例子使用一个块.
为什么Proc比基准中的块更快?这种技术允许解释器做一些优化吗?
这不是关于"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
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
正如你看到的,block并proc都采取虚拟的CPU时间相同.魔术Symbol#to_proc本身就是魔法.
正如其他人所说,这是专门针对Symbol#to_proc而不是一般的过程,并且几乎可以肯定它依赖于 ruby 实现。Symbol#to_proc在使用 ruby 本身之前,它的纯 ruby 实现肯定比等效块慢。
为了获得真正的答案,您需要在执行此类基准测试时对 ruby 进行分析。
我对 ruby 源代码的阅读是,当你调用Symbol#to_procproc 时,你得到的有点特殊:proc 的主体只是一个 C api 调用 ( rb_funcall_passing_block),而在其他情况下,它是实际的 ruby 代码,需要更长的时间才能完成。执行。