Skip to content

Instantly share code, notes, and snippets.

@dscataglini
Created December 13, 2008 02:53
Show Gist options
  • Save dscataglini/35383 to your computer and use it in GitHub Desktop.
Save dscataglini/35383 to your computer and use it in GitHub Desktop.
require 'rubygems'
require 'ruby_parser'
require 'parse_tree'
require 'benchmark'
require 'pp'
include Benchmark
a = <<-EOF
class A
def foo
1
end
end
EOF
b = <<-EOF
class B
class_eval "def foo;1;end"
end
EOF
c = <<-EOF
class C
define_method("foo"){1}
end
EOF
eval(a)
eval(b)
eval(c)
pp ParseTree.translate(A)
pp ParseTree.translate(B)
pp ParseTree.translate(C)
# This is the output from ParseTree
# [:class,
# :A,
# [:const, :Object],
# [:defn, :foo, [:scope, [:block, [:args], [:lit, 1]]]]]
# [:class,
# :B,
# [:const, :Object],
# [:defn, :foo, [:scope, [:block, [:args], [:lit, 1]]]]]
# [:class, :C, [:const, :Object], [:defn, :foo, [:bmethod, nil, [:lit, 1]]]]
t = 1_000_000
bm(50) do |x|
x.report("normal"){ t.times{ A.new.foo }}
x.report("class eval string"){ t.times{ B.new.foo }}
x.report("define method"){t.times{ C.new.foo }}
end
# This is the output of the benchmarks
#
# normal 0.660000 0.010000 0.670000 ( 0.787017)
# class eval string 0.650000 0.010000 0.660000 ( 0.729554)
# define method 1.170000 0.020000 1.190000 ( 1.379682)
# Define_method is 50+% slower.
# NOTE:
# RubyParser gives a different interpretation of the AST
pp RubyParser.new.parse(a)
pp RubyParser.new.parse(b)
pp RubyParser.new.parse(c)
# which outputs:
# s(:class,
# :A,
# nil,
# s(:scope, s(:defn, :foo, s(:args), s(:scope, s(:block, s(:lit, 1))))))
# s(:class,
# :B,
# nil,
# s(:scope, s(:call, nil, :class_eval, s(:arglist, s(:str, "def foo;1;end")))))
# s(:class,
# :C,
# nil,
# s(:scope,
# s(:iter,
# s(:call, nil, :define_method, s(:arglist, s(:str, "foo"))),
# nil,
# s(:lit, 1))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment