Percentage of time spent in method dispatch?

I was wondering if anyone had taken a look at what % of time that ruby
spends doing method dispatch?

I'll eventually do the experiments myself, but I wanted to check with
y'all to see if someone had already done some investigations. It would
be an interesting experiment to see how much you can improve method
dispatch performance by caching the reference to the method call
target, and invalidating it when the call context changes.

Thanks,
-John
http://www.iunknown.com

I'm not an internals expert, but I think the difficulty in optimizing Ruby
method dispatch is that the result of a dispatch is not determined
by the local context but instead is determined by the state of all
the module objects searched during method dispatch:
  singleton class
  class and super classes
  included modules in all of the above

Gary Wright

···

On Aug 17, 2006, at 5:05 PM, John Lam wrote:

I'll eventually do the experiments myself, but I wanted to check with
y'all to see if someone had already done some investigations. It would
be an interesting experiment to see how much you can improve method
dispatch performance by caching the reference to the method call
target, and invalidating it when the call context changes.

The current implementation has a method cache whose hit rate is above 95% or
so (don't remember the exact figure; it's not hard to reproduce anyway) ---
full method lookups are relatively rare.

Method dispatching is still fairly slow, though; I once measured that it took
some ~200 instructions to run a CFUNC, and about half as much with YARV.
Last time I read YARV's sources, it didn't have inline method caches (but it
was caching constants, IIRC), but it's been a while and they might have been
implemented meanwhile.

···

On Fri, Aug 18, 2006 at 06:05:12AM +0900, John Lam wrote:

I was wondering if anyone had taken a look at what % of time that ruby
spends doing method dispatch?

I'll eventually do the experiments myself, but I wanted to check with
y'all to see if someone had already done some investigations. It would
be an interesting experiment to see how much you can improve method
dispatch performance by caching the reference to the method call
target, and invalidating it when the call context changes.

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby

Hi,

I was wondering if anyone had taken a look at what % of time that ruby
spends doing method dispatch?

Here are some numbers. Running this code:

max = 2000
z = x = 0
while (x+=1) <= max
   y = 0
   while (y+=1) <= max
     z = (x+y-z) % 32000
   end
end

takes about 5.5s in plain Ruby 1.8.4 (on my machine).

Compiling it with Ruby2CExtension (latest version, all optimizations turned on) and then running it takes about 0.9s.

One of the optimizations is to bypass rb_call and calling the C functions of those methods (almost) directly (when possible).

If this optimization is turned off then running the compiled code takes about 3.1s. These additional 2.2s are all spent for method dispatch.

Plain Ruby spends at least the same time for method dispatch, so Ruby spends at least 40% of the time doing method dispatch (in this case).

I hope that helps,
Dominik

···

On Thu, 17 Aug 2006 23:05:12 +0200, John Lam <drjflam@gmail.com> wrote:

I'd be interested in doing some experiments with DynamicMethods in the
CLR to see what kind of performance gains can happen with method
dispatch. And direct method dispatch in the CLR is *very* fast, if we
consider that each parameter is a boxed object reference (4 bytes) and
the actuall call is a call indirect instruction. Dealing with closures
is a bit more problematic though, and making that go fast could be
difficult.

It's also fairly straightforward to substitute one dynamic method for
another one when a cache invalidation event occurs. It would be very
interesting to study the existing implementation's method cache to see
what the triggers for cache invalidation look like ...

Thanks for the input!
-John

···

On 8/17/06, Mauricio Fernandez <mfp@acm.org> wrote:

On Fri, Aug 18, 2006 at 06:05:12AM +0900, John Lam wrote:
> I was wondering if anyone had taken a look at what % of time that ruby
> spends doing method dispatch?
>
> I'll eventually do the experiments myself, but I wanted to check with
> y'all to see if someone had already done some investigations. It would
> be an interesting experiment to see how much you can improve method
> dispatch performance by caching the reference to the method call
> target, and invalidating it when the call context changes.

The current implementation has a method cache whose hit rate is above 95% or
so (don't remember the exact figure; it's not hard to reproduce anyway) ---
full method lookups are relatively rare.

Method dispatching is still fairly slow, though; I once measured that it took
some ~200 instructions to run a CFUNC, and about half as much with YARV.
Last time I read YARV's sources, it didn't have inline method caches (but it
was caching constants, IIRC), but it's been a while and they might have been
implemented meanwhile.

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby

Mauricio Fernandez wrote:

···

On Fri, Aug 18, 2006 at 06:05:12AM +0900, John Lam wrote:

I was wondering if anyone had taken a look at what % of time that ruby
spends doing method dispatch?

I'll eventually do the experiments myself, but I wanted to check with
y'all to see if someone had already done some investigations. It would
be an interesting experiment to see how much you can improve method
dispatch performance by caching the reference to the method call
target, and invalidating it when the call context changes.

The current implementation has a method cache whose hit rate is above 95% or
so (don't remember the exact figure; it's not hard to reproduce anyway) ---
full method lookups are relatively rare.

Method dispatching is still fairly slow, though; I once measured that it took
some ~200 instructions to run a CFUNC, and about half as much with YARV.
Last time I read YARV's sources, it didn't have inline method caches (but it
was caching constants, IIRC), but it's been a while and they might have been
implemented meanwhile.

I'm about to re-post my profiling of Ruby on a moderate-sized "Matrix"
benchmark. I'll post the link as soon as I get it re-run.

Hi,

Mauricio Fernandez wrote:

Method dispatching is still fairly slow, though; I once measured that it took
some ~200 instructions to run a CFUNC, and about half as much with YARV.
Last time I read YARV's sources, it didn't have inline method caches (but it
was caching constants, IIRC), but it's been a while and they might have been
implemented meanwhile.

YARV already has inline method cache (see vm.c).

···

--
// SASADA Koichi at atdot dot net

M. Edward (Ed) Borasky wrote:

Mauricio Fernandez wrote:

I was wondering if anyone had taken a look at what % of time that ruby
spends doing method dispatch?

I'll eventually do the experiments myself, but I wanted to check with
y'all to see if someone had already done some investigations. It would
be an interesting experiment to see how much you can improve method
dispatch performance by caching the reference to the method call
target, and invalidating it when the call context changes.

The current implementation has a method cache whose hit rate is above 95% or
so (don't remember the exact figure; it's not hard to reproduce anyway) ---
full method lookups are relatively rare.

Method dispatching is still fairly slow, though; I once measured that it took
some ~200 instructions to run a CFUNC, and about half as much with YARV.
Last time I read YARV's sources, it didn't have inline method caches (but it
was caching constants, IIRC), but it's been a while and they might have been
implemented meanwhile.

I'm about to re-post my profiling of Ruby on a moderate-sized "Matrix"
benchmark. I'll post the link as soon as I get it re-run.

All done and uploaded ... the link is

http://rubyforge.org/cgi-bin/viewvc.cgi/MatrixBenchmark/?root=cougar

I re-ran this in single-user mode, so there is little interference from
X, etc.

···

On Fri, Aug 18, 2006 at 06:05:12AM +0900, John Lam wrote:

M. Edward (Ed) Borasky wrote:

All done and uploaded ... the link is

http://rubyforge.org/cgi-bin/viewvc.cgi/MatrixBenchmark/?root=cougar

I re-ran this in single-user mode, so there is little interference from
X, etc.

Updated over the weekend. YARV is about four times as fast as Ruby
1.8.5! I'll probably rerun the profiling using "oprofile", though.
"gprof" seems to have too low a sampling frequency to determine what's
really going on with "reasonable" run times -- 1 to 10 minutes.

···