Projects, which use JSR292

Christian Thalinger christian.thalinger at oracle.com
Fri Feb 18 04:17:16 PST 2011


On Feb 18, 2011, at 12:52 PM, Charles Oliver Nutter wrote:
> On Fri, Feb 18, 2011 at 5:24 AM, Rémi Forax <forax at univ-mlv.fr> wrote:
>> Good news !
>> Charles does it mean that JRuby's invokedynamic now works without
>> using the previously existing logic.
>> I mean, you use only method handles from the callsite to the target method.
> 
> More and more, but definitely not completely. I'd estimate that *most*
> calls are dispatched with indy, and of those about *half* are direct
> with recent commits.
> 
> Methods that can bind all the way from caller to target must fit these criteria:
> 
> * Fixed arity
> * No block passed (block passing tends to require extra structures my
> direct indy logic doesn't set up yet)
> * One of a handful of standard signatures (just having wired all up yet)
> 
> And note that this only applies to plain calls like foo.bar; calls
> that perform dynamic dispatch but combined with other logic, like a.b
> += c, do not yet use indy at all.
> 
> I did just land another revision that allows Ruby to Ruby calls
> meeting the above criteria to bind all the way through, and
> performance dropped precipitously:
> 
> Stock JRuby:
> 
> ~/projects/jruby ➔
> JAVA_HOME=../mlvm/sources/build/bsd-i586/j2sdk-image/ jruby -X+C
> -J-XX:MaxInlineSize=150 -J-XX:InlineSmallCode=5000
> bench/bench_fib_recursive.rb 10832040
>  0.354000   0.000000   0.354000 (  0.284000)
> 832040
>  0.174000   0.000000   0.174000 (  0.174000)
> 832040
>  0.173000   0.000000   0.173000 (  0.173000)
> 832040
>  0.169000   0.000000   0.169000 (  0.169000)
> 832040
>  0.173000   0.000000   0.173000 (  0.173000)
> 
> JRuby + indy, no ruby-to-ruby calls binding directly:
> 
> ~/projects/jruby ➔
> JAVA_HOME=../mlvm/sources/build/bsd-i586/j2sdk-image/ jruby -X+C
> -Xcompile.invokedynamic=true -J-XX:+UnlockExperimentalVMOptions
> -J-XX:+EnableInvokeDynamic -J-XX:MaxInlineSize=150
> -J-XX:InlineSmallCode=5000 bench/bench_fib_recursive.rb 10
> 832040
>  0.340000   0.000000   0.340000 (  0.274000)
> 832040
>  0.150000   0.000000   0.150000 (  0.150000)
> 832040
>  0.148000   0.000000   0.148000 (  0.148000)
> 832040
>  0.147000   0.000000   0.147000 (  0.147000)
> 832040
>  0.147000   0.000000   0.147000 (  0.147000)
> 
> JRuby + indy, ruby calls binding directly:
> 
> ~/projects/jruby ➔
> JAVA_HOME=../mlvm/sources/build/bsd-i586/j2sdk-image/ jruby -X+C
> -Xcompile.invokedynamic=true -J-XX:+UnlockExperimentalVMOptions
> -J-XX:+EnableInvokeDynamic -J-XX:MaxInlineSize=150
> -J-XX:InlineSmallCode=5000 bench/bench_fib_recursive.rb 10
> 832040
>  0.883000   0.000000   0.883000 (  0.818000)
> 832040
>  0.463000   0.000000   0.463000 (  0.463000)
> 832040
>  0.463000   0.000000   0.463000 (  0.463000)
> 832040
>  0.472000   0.000000   0.472000 (  0.473000)
> 832040
>  0.459000   0.000000   0.459000 (  0.459000)
> 
> I have not investigated asm output, but it seems pretty clear that
> something very bad happens when I bind directly rather than binding
> via JRuby DynamicMethod stubs. Indeed, in the Java trace, I do see GWT
> should up:
> 
> 	at sun.dyn.MethodHandleImpl$GuardWithTest.invoke_L4(MethodHandleImpl.java:982)
> 	at ruby.__dash_e__.method__0$RUBY$foo(-e:1)
> 	at sun.dyn.MethodHandleImpl$GuardWithTest.invoke_L4(MethodHandleImpl.java:982)
> 	at ruby.__dash_e__.method__0$RUBY$foo(-e:1)
> 	at sun.dyn.MethodHandleImpl$GuardWithTest.invoke_L4(MethodHandleImpl.java:982)
> 	at ruby.__dash_e__.method__0$RUBY$foo(-e:1)
> 	at sun.dyn.MethodHandleImpl$GuardWithTest.invoke_L4(MethodHandleImpl.java:982)
> 
> But the non-direct logic includes *even more* sun.dyn and JRuby calls
> in it. How can it be so much faster? A recursive "foo" call looks like
> this:
> 
> 	at ruby.__dash_e__.method__0$RUBY$foo(-e:1)
> 	at ruby___dash_e__Invokermethod__0$RUBY$fooFixed0.call(ruby___dash_e__Invokermethod__0$RUBY$fooFixed0#foo:65535)
> 	at ruby___dash_e__Invokermethod__0$RUBY$fooFixed0.call(ruby___dash_e__Invokermethod__0$RUBY$fooFixed0#foo:65535)
> 	at sun.dyn.FilterGeneric$F6.invoke_F6(FilterGeneric.java:754)
> 	at sun.dyn.FilterGeneric$F5.invoke_F5(FilterGeneric.java:678)
> 	at sun.dyn.MethodHandleImpl$GuardWithTest.invoke_L4(MethodHandleImpl.java:982)
> 	at ruby.__dash_e__.method__0$RUBY$foo(-e:1)
> 
> With JRuby's call-site caching logic:
> 
> 	at ruby.__dash_e__.method__0$RUBY$foo(-e:1)
> 	at ruby___dash_e__Invokermethod__0$RUBY$fooFixed0.call(ruby___dash_e__Invokermethod__0$RUBY$fooFixed0#foo:65535)
> 	at ruby___dash_e__Invokermethod__0$RUBY$fooFixed0.call(ruby___dash_e__Invokermethod__0$RUBY$fooFixed0#foo:65535)
> 	at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:103)
> 	at ruby.__dash_e__.method__0$RUBY$foo(-e:1)
> 
> And with JRuby's "dynopt" mode, which emits guard, target, and
> fallback logic directly into the compiled body:
> 
> 	at rubyjit.foo_7F1E71544C0BFF52B6020F56F3C0D1A11E173AF5.__file__(-e:1)
> 	at rubyjit.foo_7F1E71544C0BFF52B6020F56F3C0D1A11E173AF5.__file__(-e:1)
> 	at rubyjit.foo_7F1E71544C0BFF52B6020F56F3C0D1A11E173AF5.__file__(-e:1)
> 	at rubyjit.foo_7F1E71544C0BFF52B6020F56F3C0D1A11E173AF5.__file__(-e:1)
> 
> Needless to day, "dynopt" (which can only do this for recursive calls)
> is still fastest on the recursive fib and tak benchmarks, but I'm a
> little confused by the degradation from directly binding ruby-to-ruby
> calls with indy. Any flags I can toss in to get you JVM guys more
> info?
> 
> And yes...this is all on JRuby master. Should be able to see the same
> effect right now.

Is there a switch to turn direct ruby-to-ruby calls on and off?  I'd like to compare inlining trees and maybe code output.

-- Christian


More information about the mlvm-dev mailing list