Here are all the possible method calls:
require 'benchmark/ips' class FooBar def name; end end el = FooBar.new Benchmark.ips do |x| x.report('plain') { el.name } x.report('eval') { eval('el.name') } x.report('method call') { el.method(:name).call } x.report('send sym') { el.send(:name) } x.report('send str') { el.send('name') } x.compare! end
And the results:
Warming up -------------------------------------- plain 236.448ki/100ms eval 20.743ki/100ms method call 131.408ki/100ms send sym 205.491ki/100ms send str 168.137ki/100ms Calculating ------------------------------------- plain 9.150M (Β± 6.5%) i/s - 45.634M in 5.009566s eval 232.303k (Β± 5.4%) i/s - 1.162M in 5.015430s method call 2.602M (Β± 4.5%) i/s - 13.009M in 5.010535s send sym 6.729M (Β± 8.6%) i/s - 33.495M in 5.016481s send str 4.027M (Β± 5.7%) i/s - 20.176M in 5.027409s Comparison: plain: 9149514.0 i/s send sym: 6729490.1 i/s - 1.36x slower send str: 4026672.4 i/s - 2.27x slower method call: 2601777.5 i/s - 3.52x slower eval: 232302.6 i/s - 39.39x slower
It was expected that a simple call would be the fastest, no additional allocations, search by characters, just searching and evaluating the method.
As for the send character through the character, it is faster than through the string, since it is much easier to allocate memory for the character. After he determined that he has been kept in memory for a long time, and there is no redistribution.
The same can be said about method(:name) (1), in order to allocate memory for the Proc (2) object, we call the method in the class, which leads to an additional search for the method, which also takes time.
eval launches the interpreter, so it is the heaviest.
mixan946 Jun 01 '17 at 20:33 on 2017-06-01 20:33
source share