Ruby 为什么proc的运行速度可能比block快?

Ruby 为什么proc的运行速度可能比block快?,ruby,internals,Ruby,Internals,在另一个问题上,他说 array.map(&:to_s) 快于 array.map { |n| n.to_s } 在第一个示例中,&将:to_s转换为一个过程。第二个示例使用一个块 为什么Proc会比基准测试中的块快?这项技术是否允许解释器进行一些优化?只是猜测,但可能是因为Proc不需要像块那样保留调用的上下文。块需要知道在它之外声明的变量,而Proc不知道。它实际上不是关于“Proc vs block” 下面是一个简单的实验(请随意复制和运行): Ruby 1.9.3p194结果

在另一个问题上,他说

array.map(&:to_s)
快于

array.map { |n| n.to_s }
在第一个示例中,
&
:to_s
转换为一个过程。第二个示例使用一个块


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

只是猜测,但可能是因为Proc不需要像块那样保留调用的上下文。块需要知道在它之外声明的变量,而Proc不知道。

它实际上不是关于“Proc vs block”

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

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)

如您所见,
block
proc
占用的CPU时间几乎相同。神奇之处在于
Symbol#to_proc
本身。

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

要得到一个真正的答案,您可能希望在执行这样一个基准测试时评测ruby


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

+1,好问题,虽然答案是针对每个Ruby实现的。我在这里添加了,Ruby中的Proc也是一个闭包(即保存上下文)。有一个非常简单的测试可以确保:这是一个非常奇怪的结果。我猜想,重复使用同一个Proc对象比重复使用一个符号创建一个要快。也许解释器不知何故完全跳过了创建Proc的工作,只是简单地做了Proc应该做的事情?(更新:啊,@frederickheung就是这么说的。)
                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)