MethodHandle vs invodynamic (performance-wise)
Rémi Forax
forax at univ-mlv.fr
Mon Feb 14 06:05:54 PST 2011
Le 14/02/2011 09:51, forum at x9c.fr a écrit :
> 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.
I should have been more clear, by invokedynamic, I mean invokedynamic if
you can't use invokevirtual/invokestatic because you know that the call
can be bound statically.
>> # 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.
That why you should use invokedynamic here. You should use guardWithTest
to create
an inlining cache at callsite to avoid the method dispatch lookup if the
receiver at callsite
as always the same type.
Instead of object.table["meth"].invokeExact you should generate
if (object.class == Foo.class)
fastpath.invokeExact // with fastpath = Foo.table["meth"]
else
object.table["meth"].invokeExact
slides 6-11 of
http://weblogs.java.net/sites/default/files/indydroid_-_FOSDEM.pdf
explain how to implement an inlining cache in Java.
>> # 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.
Yes, optimization.
>
> Kind regards,
>
> Xavier
Rémi
More information about the mlvm-dev
mailing list