为什么' eval'在红宝石中是如此之慢?

时间:2014-04-11 02:55:37

标签: ruby

在下面的红宝石代码中,' eval'比“def”慢10倍。

我理解' eval'需要解析字符串,但我想在这个例子中只需要完成一次。

require "benchmark"
GC.disable

eval "def run1; 10_000.times { #{"$a[5]\n" * 10_000} } end"
def run2
    10_000.times { "#{"$a[5]\n" * 10_000}" } 
end

$a = [1,2,3,4,5,6,7,8,9,10]

puts "run1:"
puts Benchmark.measure { run1 }

puts "run2:"
puts Benchmark.measure { run2 } 

1 个答案:

答案 0 :(得分:7)

您没有比较等效函数。 run1最终成为单个字符串中$a[5]\n 10,000次的函数,因为在调用eval之前,字符串插值是在构建字符串时发生的。 run2按照人们的预期运行。

要了解差异,请将ruby-prof投入混音:

require "benchmark"
require 'ruby-prof'

GC.disable

eval "def run1; 10_000.times { #{"$a[5]\n" * 10_000} } end"
def run2
    10_000.times { "#{"$a[5]\n" * 10_000}" } 
end

$a = [1,2,3,4,5,6,7,8,9,10]

puts "run1:"
RubyProf.start
puts Benchmark.measure { run1 }
result = RubyProf.stop
printer = RubyProf::FlatPrinter.new(result)
printer.print(STDOUT)

puts "run2:"
RubyProf.start
puts Benchmark.measure { run2 }
result = RubyProf.stop
printer = RubyProf::FlatPrinter.new(result)
printer.print(STDOUT)

编辑:这是结果(我删除了Benchmark调用以将其修改为基础)

(nick@monster)-(~/Desktop)
(523)⚡️ ruby derp.rb 
run1:
Thread ID: 2156059640
Fiber ID: 2163430960
Total: 484.962207
Sort by: self_time

 %self      total      self      wait     child     calls  name
100.00    484.962   484.962     0.000     0.000        1   Integer#times 
  0.00    484.962     0.000     0.000   484.962        1   Global#[No method] 
  0.00    484.962     0.000     0.000   484.962        1   Object#run1 

* indicates recursively called methods
run2:
Thread ID: 2156059640
Fiber ID: 2163430960
Total: 0.265188
Sort by: self_time

 %self      total      self      wait     child     calls  name
 94.02      0.249     0.249     0.000     0.000    10000   String#* 
  5.98      0.265     0.016     0.000     0.249        1   Integer#times 
  0.01      0.265     0.000     0.000     0.265        1   Global#[No method] 
  0.00      0.265     0.000     0.000     0.265        1   Object#run2 

* indicates recursively called methods