2014-04-11 6 views
2

아래의 루비 코드에서 'eval'은 'def'보다 10 배 이상 느립니다.왜 루비의 'eval'이 그렇게 느린가요?

나는 '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

를 사용하여 작은 따옴표 (나는 벤치 마크는 기본에 내려 치기 호출 제거)입니다 보간되는 것을 막기위한 eval 된 문자열의 가장 바깥 쪽 부분 (따라서 여러분이 벤치마킹한다고 생각하는 코드와는 다릅니다). 닉 브이 (Nick Veys)의 대답은 당신의 자세가 얼마나 다른지를 보여줍니다. –

답변

7

동일한 기능을 비교하고 있지 않습니다. run1은 하나의 문자열에서 $a[5]\n00000000의 함수로 끝납니다. eval이 호출되기 전에 문자열 보간이 수행되기 때문에 문자열 보간이 발생합니다. run2은 예상대로 실행됩니다.

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) 

편집 :

혼합으로 ruby-prof를 던져, 그 차이를 확인하려면 여기에 결과가

([email protected])-(~/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 
관련 문제