我最近遇到了&method(:method_name)
语法.(这使用Object#method
方法 - RDoc链接)例如,
[5, 7, 8, 1].each(&method(:puts))
Run Code Online (Sandbox Code Playgroud)
相当于
[5, 7, 8, 1].each{|number| puts number}
Run Code Online (Sandbox Code Playgroud)
在Ruby的各种实现中,与前者相比,后者是否存在性能损失?如果是这样,实施者是否正致力于改善其绩效?
Jos*_*eek 18
是的,它似乎对性能有害.
def time
start = Time.now
yield
"%.6f" % (Time.now - start)
end
def do_nothing(arg)
end
RUBY_VERSION # => "1.9.2"
# small
ary = *1..10
time { ary.each(&method(:do_nothing)) } # => "0.000019"
time { ary.each { |arg| do_nothing arg } } # => "0.000003"
# large
ary = *1..10_000
time { ary.each(&method(:do_nothing)) } # => "0.002787"
time { ary.each { |arg| do_nothing arg } } # => "0.001810"
# huge
ary = *1..10_000_000
time { ary.each(&method(:do_nothing)) } # => "37.901283"
time { ary.each { |arg| do_nothing arg } } # => "1.754063"
Run Code Online (Sandbox Code Playgroud)
看来这是在JRuby中解决的:
$ rvm use jruby
Using /Users/joshuajcheek/.rvm/gems/jruby-1.6.3
$ xmpfilter f.rb
def time
start = Time.now
yield
"%.6f" % (Time.now - start)
end
def do_nothing(arg)
end
RUBY_VERSION # => "1.8.7"
# small
ary = *1..10
time { ary.each(&method(:do_nothing)) } # => "0.009000"
time { ary.each { |arg| do_nothing arg } } # => "0.001000"
# large
ary = *1..10_000
time { ary.each(&method(:do_nothing)) } # => "0.043000"
time { ary.each { |arg| do_nothing arg } } # => "0.055000"
# huge
ary = *1..10_000_000
time { ary.each(&method(:do_nothing)) } # => "0.427000"
time { ary.each { |arg| do_nothing arg } } # => "0.634000"
Run Code Online (Sandbox Code Playgroud)
Jör*_*tag 14
由于Rubinius是最先进且最积极地优化Ruby实现的,我在Rubinius邮件列表上提出了这个问题,这就是Evan Phoenix所说的:
你可以说它与块相同的假设是,我很遗憾地说,这是错误的.有理由你没有看到
Method#to_proc
,这样的分析是2倍:
- 大多数(全部?)MRI剖面仪都没有显示MRI在C中定义的方法,因此它们永远不会出现.
- 激活已转换为a的方法的机制
Proc
全部在C中,因此开销在调用端也是不可见的.你对艺术差异的看法是正确的.另外,您认为VM可以轻松地将其优化为块是非常错误的.
Object#method
是一种不会被检测和优化的东西.此外,即使使用运行时优化,仍然需要类似转义分析的东西,因为#method
返回一个Method
您必须在其中查看并从中提取信息的对象.在调用方面,在块内联的情况下,调用的方法只能对块执行特殊操作,这是仅Rubinius具有的优化.所以要回答你的问题:
- Rubinius是否优化了此代码?不,不是吗?是的,但这并不容易.
- 及时它可以,是的.
- 它应该及时,是的.
注意:他在最后一段中提到的问题是:
- Rubinius目前是否优化了这种无点代码?
- 如果没有,可以吗?
- 如果可以,应该吗?
看起来它们在最新的ruby 1.9.2上非常相似/相同
# Using ruby 1.9.2-p290
require 'benchmark'
Benchmark.measure do
1000.times { [5, 7, 8, 1].each(&method(:puts)) }
end
# => 0.020000 0.020000 0.040000 ( 0.066408)
# => 0.020000 0.010000 0.030000 ( 0.075474)
# => 0.020000 0.020000 0.040000 ( 0.048462)
Benchmark.measure do
1000.times { [5, 7, 8, 1].each{|number| puts number} }
end
# => 0.020000 0.020000 0.040000 ( 0.071505)
# => 0.020000 0.020000 0.040000 ( 0.062571)
# => 0.010000 0.020000 0.030000 ( 0.040944)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3377 次 |
最近记录: |