MethodHandle vs invodynamic (performance-wise)

forum at x9c.fr forum at x9c.fr
Mon Feb 14 00:51:27 PST 2011


Le 13 févr. 2011 à 20:38, Rémi Forax a écrit :

> On 02/13/2011 07:00 PM, forum at x9c.fr wrote:
>> Le 13 févr. 2011 à 12:55, Rémi Forax a écrit :

(...)


>>  is there a reasonable estimate of the different
>> speeds (supposing that the target would indeed be constant). I mean, is
>> the gap as huge as between reflection and handles?
>> 
> 
> No, the gap is not as huge. Theorically, if the method handle is stored
> in a static final field, the difference is just a pointer check.

(...)


>>> Anyway, as you see you should choose to use one mechanism or the other 
>>> depending
>>> on the use case and not on some benchmark.
>>> 
>> Well, I do not fully understand your point. To some extend, it appears to me
>> that both mechanisms can be used to achieve the very same effect. That's
>> why I thought the "director's cut" should be performances.
>> 
> 
> if you know the method handle at link time, you should use invokedynamic,
> if you don't know you should use MH.invokeExact.

Very valuable information, and rule of thumb -- thanks.

(...)


> From performance point of view is better to have unrelated final classes
> instead of a hierarchy. double, closure etc. can be represented as
> Double, MethodHandle (or a class that wraps MethodHandle) etc
> and use Object as common super type.

My explanation was coarse-grained; there is a 'Value' parent, and then
almost all other classes are final children of 'Value'. I acknowledge a
little penalty over your suggestion, but my motto could be "safety first".
I do not want anyone to pass a child of 'Object' that cannot be handled
as a proper language value.


>>  There again, I wonder if the best is to do a
>> "Method.invokeExact(-)" or to play with the "invokedynamic" instruction.
>> The former has been implemented easily and is indeed quite fast.
>> Is it a good investment to move to le latter, given that it will
>> probably entail compile-time generation of one class per target in
>> my case ?
>> 
> 
> Having one class per target is not a requirement at all.
> invokedynamic is just a way to install a method handle at a callsite.
> Let's take examples (sorry my Caml is a little rusty):

Rusty or not (an as far as I can tell it is not), it is always a pleasure to
encounter someone talking Caml outside of the caml-list...


> #
>  let rec fib n =
>    if n < 1 then 1 else fib(n-1) + fib(n-2);;
> 
> 
> here fib(n-1) and fib(n-2) should be encoded using invokedynamic.

Why? they are currently (and happily) encoded using an "invokestatic"
instruction (every Caml function being encoded as a "static" method),
given that the function to be called is known at compile time.


> # p#get_x;;
> 
> p#get_x is also an invokedynamic.

This one is a tricky one...
For non-camlists "obj#meth" is the syntax for calling the method "meth"
over the object "obj". This is tricky because Java and Caml objects are
*really* different (e. g. nominal vs structural typing) and to be compatible
with the original Caml implementation, I have constraints over the way
to encode an object instance. To put it short, it entails having a table for
method dispatch, that maps method identifiers to closures.


> # let f = (function x -> 1);;
> 
> here f should be a MethodHandle so
> 
> # f 1;;
> is a call to MethodHandle.invokeExact()

Well, there again, the call to "f" is static as known at compile-time.
But if "f" was actually a parameter to an higher-order function,
an handle for "f" would have been retrieved from the static
method corresponding to the function, and called through
"invokeExact" from the higher-order function.


Kind regards,

Xavier


More information about the mlvm-dev mailing list