MethodHandle performance

Stephen Colebourne scolebourne at joda.org
Thu Jan 12 18:12:49 UTC 2017


@Claes

Fat fingers - should have been 1.8.0_112

The code is in the link:
https://github.com/JodaOrg/joda-beans/commit/ad7d61a7ff72f932957127117dd8f377e1e2bf60

where a HandleMetaBean (method handle) performs the same job as
LightMetaBean (reflection) as shown in the non-JMH test
TestHandle.main().

@Jochen

The method handle setup code is all done in static initializers. The
performance tests are all testing runtime usage, excluding the static
initializer setup cost (as one off startup costs are not relevant to
my use case).

@Remi
Thanks for taking a look. Its the constructor invocation that is most
obviously a problem. In HandleMetaBean.build(Object[]) where it uses
invokeWithArguments(Object[]). I get 1650ms for reflection vs 3500ms
for method handles.

The meta-property getter code runs much quicker, so a JMH test would
really be needed to confirm the difference there.

The asType() and invokeExact() code was added to see if that made a
difference, but it did not.

@Aleksey
I saw you post when researching before writing my mail today. The code
cannot use static final method handles (I doubt there are many use
cases for those, to be honest). The goal of the code here is to obtain
an object implementing my interfaces that can be invoked in a general
way to invoke a constructor or a getter. As such, the method handles
need to be instance variables.

I have now done a JMH test.

The good news is that the method handle for the getter is slightly
faster when taken in isolation:

JodaBenchmark.testMethodHandleGet    avgt   50    8.421 ± 0.078  ns/op
JodaBenchmark.testReflectionGet      avgt   50   11.003 ± 0.050  ns/op

The bad news is that the method handle constructor call is not 2x
reflection, but 6x:

JodaBenchmark.testMethodHandleBuild  avgt   50  219.212 ± 2.400  ns/op
JodaBenchmark.testReflectionBuild    avgt   50   36.012 ± 0.167  ns/op

This test reduced the difference to :
   return (T) constructorHandle.invokeWithArguments(args);
vs
    return constructor.newInstance(args);

Email me privately for a zip of the JMH test:

Any thoughts on the 6x slower call? thanks for looking
Stephen


On 12 January 2017 at 14:47, Claes Redestad <claes.redestad at oracle.com> wrote:
> Hi Stephen,
>
> this is surprising; handles should typically be as fast or much
> faster than reflection (VarHandles can be faster than Unsafe in certain
> cases), but may carry a slightly more expensive setup cost - do you have a
> reproducer I could try?
>
> 8b122 - do you mean 8u122 EA?
>
> Thanks!
>
> /Claes
>
>
> On 2017-01-12 15:23, Stephen Colebourne wrote:
>>
>> I've recently tried [1] converting Joda-Beans use of setAccessible()
>> to use MethodHandle. Since it is a code generator, the actual coding
>> is relatively easy, and obtaining the MethodHandles.Lookup instance
>> with the "private" capability is simple. While the MethodHandles API
>> looks very complex, it isn't too bad to use, although it is
>> undoubtedly more complex than reflection.
>>
>> (Note that the standard Joda-Beans technique is to code generate
>> normal Java code to avoid the need to use reflection, but it can
>> optionally generate reflection-based code in "light bean" mode. It is
>> that reflection approach that is being examined here).
>>
>> The real problem however is performance. In my tests, I am seeing a
>> MethodHandle approach being 2 to 3 times slower than a reflection
>> approach for identical functionality, which is quite a significant
>> degradation. (using Java 8 b122)
>>
>> Given the performance, I left to question whether the repeated Jigsaw
>> advice to use MethodHandle instead of setAccessible is viable - in the
>> kinds of places that use reflection, performance tends to be critical.
>> Is there, or has there been, work in Java 9 to improve the performance
>> of method handles?
>>
>> Stephen
>>
>> [1] https://github.com/JodaOrg/joda-beans/commits/wip/methodhandles
>>
>


More information about the jigsaw-dev mailing list