MethodHandle.invoke* performance

Remi Forax forax at univ-mlv.fr
Wed Apr 3 09:27:51 PDT 2013


On 04/03/2013 06:12 PM, Cédric Champeau wrote:
> Le 03/04/2013 17:50, Remi Forax a écrit :
>> Sorry to be rude, but it's still a micro-benchmark ...
> First of all, yes, it is :) And as the classical fibonacci benchmark,
> it's useless but relevant for understanding how things work :)
>> for invokedynamic, it's not in theory, if your method handle is constant
>> either because it's a static final or because it is nested in a
>> CallSite, it's constant for the JIT, thus fully optimized.
>>
>> for method handle on stack, the method handle is obviously not constant
>> moreover the JIT is not able use trick to make it constant (like
>> hoisting it out of the loop,
>> or doing the inlining algorithm in a backward way etc.)
>> More on that later ...
> Well, even if I make my MH variable declaration "final", the performance
> is the same, so I assume there's no local analysis, right?

'final' on a local variable is a modifier for the compiler, not for the JIT.
There are several local analysis, but not the ones you think.

>> As you said it's a micro-benchmark so you end up with unusual good
>> performance,
>> by example the call to j.l.r.Method is optimized as never it will be in
>> a real program
>> (you call the method in the same unit it was declared and
>> you have less than 3 instances of Method that are called more than 60
>> times).
>>
>> Now, Krystal is currently working to add a cache when a method handle is
>> called,
>> so in few betas, the performance of method handles of your
>> micro-benchmark will improve dramatically.
> That's good to know :)
>> And the cache of MethodHandle is better that the cache which is used for
>> j.l.r.Method because it can be local to a callsite and not global (in
>> fact local to one callsite in the code of j.l.r.Method that is used by
>> the invocation path when you call "invoke").
>>
>> Anyway, because it's a micro-benchmark the result will be as useless as
>> now to predict the behaviour of a real world program.
> I can perfectly understand why some path is optimized or not, what I
> find surprising is more the order of magnitude here. So yes, calling
> invoke() takes more than 50s where reflection takes only 1.2s, and even
> invokeExact is slower (~3 to 1). My point is more than if MethodHandles
> are branded as "faster" than reflection (I heard you say it ;)), then
> there is something wrong.

I say that in the context of proxies, i.e. where you can emit an 
invokedynamic to store the method handle at callsite, method handle are 
faster than using reflection because you don't need proxies anymore 
(remember I said that too :).

> You should expect people doing stupid things  like me, thinking it will be faster than plain reflection. At least, the  docs should mention something about performance.

The javadoc is the spec, we are talking about the Oracle implementation 
of the spec.
On Android, Jerome and I have run some tests that shows that a 
MethodHandle.invokeExact is always faster than a call to the Reflection, 
it's just because the reflection is super slow on Android not the opposite.

>> cheers,
>> Rémi
> Thanks for your answer :)

Rémi



More information about the mlvm-dev mailing list