Does this benchmark make sense?

Hello,

I was playing around with some Ruby features and benchmarked the
following, showing that making a class call using “self.method” is
faster than doing the same using “Classname.method”. Doesn’t make much
sense to me, but I’m not much of a benchmarker, so am hoping someone
will comment on this.

require ‘benchmark’

class VarEval
@@t=10

def self.t
@@t
end

def t
@@t
end

def self.time
n=5_000_000
Benchmark.bm do |x|
x.report(“direct”) { n.times { VarEval.t } }
x.report(“send”) { n.times { VarEval.send(:t) } }
x.report(“eval”) { n.times { eval("@@#{‘t’}") } }
end
end

def self.time2
n=5_000_000
Benchmark.bm do |x|
x.report(“direct”) { n.times { self.t } }
x.report(“send”) { n.times { self.send(:t) } }
x.report(“eval”) { n.times { eval("@@#{‘t’}") } }
end
end

def time
n=5_000_000
Benchmark.bm do |x|
x.report(“direct”) { n.times { self.class.t } }
x.report(“send”) { n.times { self.class.send(:t) } }
x.report(“eval”) { n.times { eval("@@#{‘t’}") } }
end
end

def sanity
puts “self.t=”,self.t
puts “self.class.t=”,self.class.t
puts %w{eval("@@#{‘t’}")},eval("@@#{‘t’}")
end

def self.sanity
puts “self.t=”,self.t
puts “VarEval.t=”,VarEval.t
puts %w{eval("@@#{‘t’}")},eval("@@#{‘t’}")
end

end

VarEval.sanity

VarEval.new.sanity

VarEval.time
VarEval.time2
VarEval.new.time

RESULTS in ORDER for

VarEval.time

VarEval.time2

VarEval.new.time

5_000_000 tries

user system total real

direct 2.230000 0.010000 2.240000 ( 2.313980)

send 2.830000 0.020000 2.850000 ( 2.919039)

eval 11.440000 0.050000 11.490000 ( 11.667510)

user system total real

direct 1.880000 0.010000 1.890000 ( 1.900675)

send 2.460000 0.010000 2.470000 ( 2.509326)

eval 11.440000 0.050000 11.490000 ( 11.688772)

user system total real

direct 2.360000 0.010000 2.370000 ( 2.395637)

send 2.970000 0.010000 2.980000 ( 3.011359)

eval 11.460000 0.050000 11.510000 ( 11.651057)

On Thu, May 31, 2007 at 08:12:34AM +0900, Farhad F. wrote:

I was playing around with some Ruby features and benchmarked the
following, showing that making a class call using “self.method” is
faster than doing the same using “Classname.method”.

By a tiny margin:

[self.x]

user system total real

direct 2.230000 0.010000 2.240000 ( 2.313980)

send 2.830000 0.020000 2.850000 ( 2.919039)

eval 11.440000 0.050000 11.490000 ( 11.667510)


[Klassname.x]

user system total real

direct 2.360000 0.010000 2.370000 ( 2.395637)

send 2.970000 0.010000 2.980000 ( 3.011359)

eval 11.460000 0.050000 11.510000 ( 11.651057)

Doesn’t make much sense to me

“self” doesn’t involve looking up a constant; “Klassname” does.

Brian C. wrote:

On Thu, May 31, 2007 at 08:12:34AM +0900, Farhad F. wrote:

I was playing around with some Ruby features and benchmarked the
following, showing that making a class call using “self.method” is
faster than doing the same using “Classname.method”.

By a tiny margin:

[self.x]

user system total real

direct 2.230000 0.010000 2.240000 ( 2.313980)

send 2.830000 0.020000 2.850000 ( 2.919039)

eval 11.440000 0.050000 11.490000 ( 11.667510)


[Klassname.x]

user system total real

direct 2.360000 0.010000 2.370000 ( 2.395637)

send 2.970000 0.010000 2.980000 ( 3.011359)

eval 11.460000 0.050000 11.510000 ( 11.651057)

Doesn’t make much sense to me

“self” doesn’t involve looking up a constant; “Klassname” does.

Thanks - actually, I believe that the correct comparison is:
[self.x]

user system total real

direct 1.880000 0.010000 1.890000 ( 1.900675)

send 2.460000 0.010000 2.470000 ( 2.509326)

eval 11.440000 0.050000 11.490000 ( 11.688772)

[Klassname.x]

user system total real

direct 2.230000 0.010000 2.240000 ( 2.313980)

send 2.830000 0.020000 2.850000 ( 2.919039)

eval 11.440000 0.050000 11.490000 ( 11.667510)

As expected, the eval is the same, but in both the send and the direct
call method, there is about a 0.35 second difference, which is a
substantial percentage. Seems to be an expensive symbol lookup
operation…

On Thu, May 31, 2007 at 04:13:26PM +0900, Farhad F. wrote:

user system total real

direct 2.230000 0.010000 2.240000 ( 2.313980)

send 2.830000 0.020000 2.850000 ( 2.919039)

eval 11.440000 0.050000 11.490000 ( 11.667510)

OK, checking again:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/253666

So, “Klassname.t” and “self.class.t” are almost identical (where ‘self’
is
an instance of Klassname), but “Klassname.t” is slower than “self.t”
(where
‘self’ is Klassname).

OK, it’s a bit odd :slight_smile: