As Jochen says,
package java.lang.invoke is optimized to make invokeExact fast 
(especially with primitive),
not lookup.findVirtual, asType, bindTo etc.

The difference between reflection and method handle is when the security 
check occurs.
lookup.findVirtual does the security check and invoke/invokeExact don't.
getMethod() don't do the security check and invoke does (but it cache 
the result).

Also, you have a way to avoid lookup by encoding a method handle 
constant directly
in the bytecode and use LDC to load it.
But there is no syntax for that currently in Java (the language).

You can also use lookup.unreflectMethod to transform a j.l.r.Method to a 
j.l.i.MethodHandle
(and also call setAccessible on the method to avoid the security check).

For asType, invokeExact() only work if the type of its parameter (the 
declared one, no the runtime one)
is exactly the same as the method type returned by the method handle.
So if you want to call (String)method.invokeExact(receiver, 
"methodhandle", the method type
must be (Object,String)String.
When you do a lookup.findVirtual on by example Foo, the method type is 
(Foo,String)String
so you need to convert it to (Object,String)String or to use invoke 
instead of invokeExact.

Rémi

On 07/09/2011 03:08 PM, Hiroshi Nakamura wrote:
> Hello,
>
> Thanks for your swift responses.
>
> On Sat, Jul 9, 2011 at 19:29, Rémi Forax<fo...@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
> _______________________________________________
> mlvm-dev mailing list
> mlvm-dev@openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to