MethodHandle lookup&invocation performance
Hiroshi Nakamura
nakahiro at gmail.com
Sat Jul 9 06:08:47 PDT 2011
Hello,
Thanks for your swift responses.
On Sat, Jul 9, 2011 at 19:29, Rémi Forax <forax at univ-mlv.fr> wrote:
>> You should avoid to create constants more than once.
Indeed. I updated the benckmark. (please see below)
>> Also, bindTo() will create a method handle for-each call.
Sure, but 'bindTo(rec).invokeExact(arg)' looks faster than
'invoke(rec, arg)' for this microbenchmark.
>> or like that:
>>
>> private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
>> private static final MethodType mt = MethodType.methodType(String.class, String.class);
>> private static final MethodType mt2 = MethodType.methodType(String.class, Object.class, String.class);
>>
>> private static MethodHandle methodhandleLookup(Object receiver, String methodName) throws Throwable {
>> MethodHandle mh = lookup.findVirtual(receiver.getClass(), methodName, mt);
>> return mh.asType(mt2);
>> }
>>
>> private static String methodhandleInvoke(Object receiver, MethodHandle method) throws Throwable {
>> return (String) method.bindTo(receiver).invokeExact(receiver, "methodhandle");
>> }
>
> oups, typo:
>
> private static String methodhandleInvoke(Object receiver, MethodHandle method) throws Throwable {
> return (String) method.invokeExact(receiver, "methodhandle");
> }
Thank you very much. I didn't understand asType well.
Here's the updated code:
https://raw.github.com/nahi/jsr292-sandbox/master/src/jp/gr/java_conf/jruby/MethodHandleTest.java
and the benchmark result follows. I updated 'methodhandle' as
'methodhandle1' to use constants, and added 'methodhandle2' which uses
'asType'. Interestingly, 'methodhandle2' invocation perf got as fast
as reflection, but lookup got slower than 'methodhandle1'.
-- 0
methodhandle1 lookup * 100000: 557.97 [msec], average: 5.58 [nsec]
methodhandle1 lookup+invoke * 100000: 431.21 [msec], average: 4.31 [nsec]
methodhandle2 lookup * 100000: 413.81 [msec], average: 4.14 [nsec]
methodhandle2 lookup+invoke * 100000: 297.56 [msec], average: 2.98 [nsec]
reflection lookup * 100000: 99.52 [msec], average: 1.00 [nsec]
reflection lookup+invoke * 100000: 181.40 [msec], average: 1.81 [nsec]
-- 1
methodhandle1 lookup * 100000: 192.42 [msec], average: 1.92 [nsec]
methodhandle1 lookup+invoke * 100000: 289.65 [msec], average: 2.90 [nsec]
methodhandle2 lookup * 100000: 267.24 [msec], average: 2.67 [nsec]
methodhandle2 lookup+invoke * 100000: 327.26 [msec], average: 3.27 [nsec]
reflection lookup * 100000: 38.44 [msec], average: 0.38 [nsec]
reflection lookup+invoke * 100000: 65.53 [msec], average: 0.66 [nsec]
-- 2
methodhandle1 lookup * 100000: 176.79 [msec], average: 1.77 [nsec]
methodhandle1 lookup+invoke * 100000: 270.87 [msec], average: 2.71 [nsec]
methodhandle2 lookup * 100000: 259.02 [msec], average: 2.59 [nsec]
methodhandle2 lookup+invoke * 100000: 289.60 [msec], average: 2.90 [nsec]
reflection lookup * 100000: 31.77 [msec], average: 0.32 [nsec]
reflection lookup+invoke * 100000: 104.24 [msec], average: 1.04 [nsec]
-- 3
methodhandle1 lookup * 100000: 220.45 [msec], average: 2.20 [nsec]
methodhandle1 lookup+invoke * 100000: 282.01 [msec], average: 2.82 [nsec]
methodhandle2 lookup * 100000: 265.23 [msec], average: 2.65 [nsec]
methodhandle2 lookup+invoke * 100000: 299.53 [msec], average: 3.00 [nsec]
reflection lookup * 100000: 39.24 [msec], average: 0.39 [nsec]
reflection lookup+invoke * 100000: 70.76 [msec], average: 0.71 [nsec]
-- 4
methodhandle1 lookup * 100000: 183.54 [msec], average: 1.84 [nsec]
methodhandle1 lookup+invoke * 100000: 268.61 [msec], average: 2.69 [nsec]
methodhandle2 lookup * 100000: 262.18 [msec], average: 2.62 [nsec]
methodhandle2 lookup+invoke * 100000: 284.43 [msec], average: 2.84 [nsec]
reflection lookup * 100000: 28.34 [msec], average: 0.28 [nsec]
reflection lookup+invoke * 100000: 62.86 [msec], average: 0.63 [nsec]
-- 5
methodhandle1 lookup * 100000: 182.89 [msec], average: 1.83 [nsec]
methodhandle1 lookup+invoke * 100000: 260.14 [msec], average: 2.60 [nsec]
methodhandle2 lookup * 100000: 262.31 [msec], average: 2.62 [nsec]
methodhandle2 lookup+invoke * 100000: 284.80 [msec], average: 2.85 [nsec]
reflection lookup * 100000: 28.60 [msec], average: 0.29 [nsec]
reflection lookup+invoke * 100000: 67.08 [msec], average: 0.67 [nsec]
-- 6
methodhandle1 lookup * 100000: 191.14 [msec], average: 1.91 [nsec]
methodhandle1 lookup+invoke * 100000: 260.52 [msec], average: 2.61 [nsec]
methodhandle2 lookup * 100000: 246.75 [msec], average: 2.47 [nsec]
methodhandle2 lookup+invoke * 100000: 282.33 [msec], average: 2.82 [nsec]
reflection lookup * 100000: 28.98 [msec], average: 0.29 [nsec]
reflection lookup+invoke * 100000: 66.73 [msec], average: 0.67 [nsec]
-- 7
methodhandle1 lookup * 100000: 182.27 [msec], average: 1.82 [nsec]
methodhandle1 lookup+invoke * 100000: 260.33 [msec], average: 2.60 [nsec]
methodhandle2 lookup * 100000: 255.34 [msec], average: 2.55 [nsec]
methodhandle2 lookup+invoke * 100000: 290.13 [msec], average: 2.90 [nsec]
reflection lookup * 100000: 30.20 [msec], average: 0.30 [nsec]
reflection lookup+invoke * 100000: 72.33 [msec], average: 0.72 [nsec]
-- 8
methodhandle1 lookup * 100000: 176.21 [msec], average: 1.76 [nsec]
methodhandle1 lookup+invoke * 100000: 267.92 [msec], average: 2.68 [nsec]
methodhandle2 lookup * 100000: 261.67 [msec], average: 2.62 [nsec]
methodhandle2 lookup+invoke * 100000: 285.91 [msec], average: 2.86 [nsec]
reflection lookup * 100000: 34.12 [msec], average: 0.34 [nsec]
reflection lookup+invoke * 100000: 68.78 [msec], average: 0.69 [nsec]
-- 9
methodhandle1 lookup * 100000: 181.78 [msec], average: 1.82 [nsec]
methodhandle1 lookup+invoke * 100000: 265.34 [msec], average: 2.65 [nsec]
methodhandle2 lookup * 100000: 252.99 [msec], average: 2.53 [nsec]
methodhandle2 lookup+invoke * 100000: 299.42 [msec], average: 2.99 [nsec]
reflection lookup * 100000: 31.08 [msec], average: 0.31 [nsec]
reflection lookup+invoke * 100000: 66.65 [msec], average: 0.67 [nsec]
Am I still missing something?
Regards,
// NaHi
More information about the mlvm-dev
mailing list