MethodHandle performance

Michael Rasmussen michael.rasmussen at zeroturnaround.com
Thu Jan 12 19:46:49 UTC 2017


Doing a quick JMH benchmark here, with a constructor taking 4
arguments, invokeWithArguments was about 15-30x slower than invoke and
invokeExact.
Otherwise, static final MH was 2.5x faster then reflection, and
instance field MH was 1.3x faster

For output and test code:
https://gist.github.com/anonymous/32e698d04c7456c10f069686072d7cc6

/Michael

On 12 January 2017 at 20:12, Stephen Colebourne <scolebourne at joda.org> wrote:
> @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