I'm trying to figure out why polymorphic dispatch is incredibly slow
in JRuby + indy. Take this benchmark, for example:

class A; def foo; end; end
class B; def foo; end; end

a = A.new
b = B.new

5.times { puts Benchmark.measure { 1000000.times { a, b = b, a; a.foo;
b.foo } } }

a.foo and b.foo are bimorphic here. Under stock JRuby, using
CachingCallSite, this benchmark runs in about 0.13s per iteration.
Using invokedynamic, it takes 9s!!!

This is after a patch I just committed that caches the target method
handle for direct paths. I believe the only thing created when GWT
fails now is a new GWT.

Is it expected that rebinding a call site or constructing a GWT would
be very expensive? If yes...I will have to look into having a hard
failover to inline caching or a PIC-like handle chain for polymorphic
cases. That's not necessarily difficult. If no...I'm happy to update
my build and play with patches to see what's happening here.

A sampled profile produced the following output:

         Stub + native   Method
 57.6%     0  +  5214    java.lang.invoke.MethodHandleNatives.init
 30.9%     0  +  2798    java.lang.invoke.MethodHandleNatives.init
  2.1%     0  +   189    java.lang.invoke.MethodHandleNatives.getTarget
  0.1%     0  +     7    java.lang.Object.getClass
  0.0%     0  +     3    java.lang.Class.isPrimitive
  0.0%     0  +     3    java.lang.System.arraycopy
 90.7%     0  +  8214    Total stub

Of course we all know how accurate sampled profiles are, but this is
pretty a pretty dismal result.

I suspect that this polymorphic cost is a *major* factor in slowing
down some benchmarks under invokedynamic. FWIW, the above benchmark
without the a,b swap runs in 0.06s, better than 2x faster than stock
JRuby (yay!).

- Charlie
_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to