Right, I was just looking at the micro Stephen provided me, and it does
seem that the added cost for this case is due to invokeWithArguments
creating a new invoker every time.
This appears to be a known issue[1], so a design that can use invoke or
invokeExact instead should be considered:
- this.constructor = constructorHandle;
+ this.constructor = constructorHandle.asSpreader(Object[].class,
propertyTypes.size());
...
- return (T) constructor.invokeWithArguments(args);
+ return (T) constructor.invoke(args);
This seems sufficient to get the MH-based implementation on par with
the reflection based one in all tests.
Thanks!
/Claes
[1] https://bugs.openjdk.java.net/browse/JDK-8078511
On 2017-01-12 20:46, Michael Rasmussen wrote:
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 <scolebou...@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.redes...@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