Sure: there you go, in a somewhat clinical testcase.
----------------- snip -----------------
require “benchmark”
CNT=200000
Benchmark.bm { |x|
x.report “V1” do
(1…CNT).each do [1].each { |i| i.to_i } end
end
}
class Symbol
def to_proc; Proc.new { |*args| args.shift.send(self, *args) };
end
end
Benchmark.bm { |x|
x.report “V2” do
(1…CNT).each do [].each (&:to_i) end
end
}
class Symbol
def to_proc; Proc.new { |obj| obj.send(self) }; end
end
Benchmark.bm { |x|
x.report “V3” do
(1…CNT).each do [1].each (&:to_i) end
end
}
class Symbol
def to_proc; @proc ||= Proc.new { |*args| args.shift.send(self,
*args) }; end
end
Benchmark.bm { |x|
x.report “V4” do
(1…CNT).each do [1].each (&:to_i) end
end
}
----------------- snap ----------------
The result is on my machine as follows:
user system total real
V1 0.200000 0.000000 0.200000 ( 0.201815)
user system total real
V2 0.860000 0.000000 0.860000 ( 0.870993)
user system total real
V3 0.950000 0.000000 0.950000 ( 0.953523)
user system total real
V4 0.680000 0.010000 0.690000 ( 0.685361)
The fastest, V1, doesn’t build proc objects at all. V2 is rails’
default implementation, V4 caches the Proc objects inside the symbol,
i.e. generates the Proc object only.
Of course, invoking 200000 Proc objects this way is usually not what
you are doing in any application; we, however, had a test case where
we did it 9000 times per action and it matched badly with the garbage
collector. Ruby enterprise behaved much much better
/eno