MethodHandle lookupinvocation performance

2011-07-09 Thread Hiroshi Nakamura
Hello,

I heard that jsr292 makes dynamic method lookupinvocation faster than
reflection so I did some performance comparison against plain
reflection. I'm sending this mail since the result looks strange to
me.

Code is here:
https://raw.github.com/nahi/jsr292-sandbox/master/src/jp/gr/java_conf/jruby/MethodHandleTest.java

And here's the result of above code on my linux 64bit box.

% uname -a
Linux ubuntu 2.6.39-0-generic #5~20110427-Ubuntu SMP Wed Apr 27
15:27:41 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux
% /home/nahi/java/jdk1.7.0b147/bin/java -version
java version 1.7.0
Java(TM) SE Runtime Environment (build 1.7.0-b147)
Java HotSpot(TM) 64-Bit Server VM (build 21.0-b17, mixed mode)
% /home/nahi/java/jdk1.7.0b147/bin/java -cp
out/production/jsr292-sandbox/ jp.gr.java_conf.jruby.MethodHandleTest
-- 0
methodhandle lookup* 10: 584.48 [msec], average:   5.84 [nsec]
methodhandle lookup+invoke * 10: 420.05 [msec], average:   4.20 [nsec]
reflection   lookup* 10:  96.72 [msec], average:   0.97 [nsec]
reflection   lookup+invoke * 10: 161.51 [msec], average:   1.62 [nsec]
-- 1
methodhandle lookup* 10: 184.66 [msec], average:   1.85 [nsec]
methodhandle lookup+invoke * 10: 290.20 [msec], average:   2.90 [nsec]
reflection   lookup* 10:  27.19 [msec], average:   0.27 [nsec]
reflection   lookup+invoke * 10:  62.92 [msec], average:   0.63 [nsec]
-- 2
methodhandle lookup* 10: 182.42 [msec], average:   1.82 [nsec]
methodhandle lookup+invoke * 10: 293.39 [msec], average:   2.93 [nsec]
reflection   lookup* 10:  30.18 [msec], average:   0.30 [nsec]
reflection   lookup+invoke * 10:  62.91 [msec], average:   0.63 [nsec]
-- 3
methodhandle lookup* 10: 182.37 [msec], average:   1.82 [nsec]
methodhandle lookup+invoke * 10: 245.75 [msec], average:   2.46 [nsec]
reflection   lookup* 10:  27.13 [msec], average:   0.27 [nsec]
reflection   lookup+invoke * 10:  58.63 [msec], average:   0.59 [nsec]
-- 4
methodhandle lookup* 10: 173.80 [msec], average:   1.74 [nsec]
methodhandle lookup+invoke * 10: 239.77 [msec], average:   2.40 [nsec]
reflection   lookup* 10:  29.21 [msec], average:   0.29 [nsec]
reflection   lookup+invoke * 10:  63.65 [msec], average:   0.64 [nsec]
-- 5
methodhandle lookup* 10: 188.05 [msec], average:   1.88 [nsec]
methodhandle lookup+invoke * 10: 247.05 [msec], average:   2.47 [nsec]
reflection   lookup* 10:  27.80 [msec], average:   0.28 [nsec]
reflection   lookup+invoke * 10:  61.39 [msec], average:   0.61 [nsec]
-- 6
methodhandle lookup* 10: 181.78 [msec], average:   1.82 [nsec]
methodhandle lookup+invoke * 10: 248.66 [msec], average:   2.49 [nsec]
reflection   lookup* 10:  29.58 [msec], average:   0.30 [nsec]
reflection   lookup+invoke * 10:  64.29 [msec], average:   0.64 [nsec]
-- 7
methodhandle lookup* 10: 178.12 [msec], average:   1.78 [nsec]
methodhandle lookup+invoke * 10: 255.79 [msec], average:   2.56 [nsec]
reflection   lookup* 10:  28.21 [msec], average:   0.28 [nsec]
reflection   lookup+invoke * 10:  60.76 [msec], average:   0.61 [nsec]
-- 8
methodhandle lookup* 10: 172.35 [msec], average:   1.72 [nsec]
methodhandle lookup+invoke * 10: 252.54 [msec], average:   2.53 [nsec]
reflection   lookup* 10:  28.52 [msec], average:   0.29 [nsec]
reflection   lookup+invoke * 10:  67.25 [msec], average:   0.67 [nsec]
-- 9
methodhandle lookup* 10: 181.18 [msec], average:   1.81 [nsec]
methodhandle lookup+invoke * 10: 250.97 [msec], average:   2.51 [nsec]
reflection   lookup* 10:  27.14 [msec], average:   0.27 [nsec]
reflection   lookup+invoke * 10:  62.53 [msec], average:   0.63 [nsec]

Hotspot benchmarking is hard and I would be missing something. Am I
doing it wrong? Can I expect jsr292 invocation to be faster than
reflection?

Regards,
// NaHi
___
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev


Auto Reply: MethodHandle lookupinvocation performance

2011-07-09 Thread bertrand . delsart
Sorry, I'm away till August 1st.

For urgent matters, please contact David.Therkelsen
___
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev


Re: MethodHandle lookupinvocation performance

2011-07-09 Thread Jochen Theodorou
Am 09.07.2011 10:48, schrieb Hiroshi Nakamura:
 Hello,

 I heard that jsr292 makes dynamic method lookupinvocation faster than
 reflection so I did some performance comparison against plain
 reflection. I'm sending this mail since the result looks strange to
 me.

 Code is here:
 https://raw.github.com/nahi/jsr292-sandbox/master/src/jp/gr/java_conf/jruby/MethodHandleTest.java

lookup I don't know. I am not sure about the recent versions, I think 
the lookup is using the same core as Reflection plus additional 
checks. I don't expect that to be faster. It would be very nice though.

The performance of the invocation cannot be meassured like you do it I 
think. The big pro comes from the ability to inline the method calls, 
but this is only present if you use the invokedynamic bytecode 
instruction. There is currently no way in Java to express invokedynamic.

And a third point... even if there where invokedynamic used, I think in 
your case it would not really bring forth the real performance 
possibilities, since your receiver is changing all the time.

But in general I must say, I would have expected the performance to be 
at least near Reflection as well. I mean the situation is for Reflection 
not all that better.

bye blackdrag

-- 
Jochen blackdrag Theodorou
The Groovy Project Tech Lead
http://blackdragsview.blogspot.com/
For Groovy programming sources visit http://groovy.codehaus.org

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


Auto Reply: Re: MethodHandle lookupinvocation performance

2011-07-09 Thread bertrand . delsart
Sorry, I'm away till August 1st.

For urgent matters, please contact David.Therkelsen
___
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev


Re: MethodHandle lookupinvocation performance

2011-07-09 Thread Rémi Forax
You should avoid to create constants more than once.
Also, bindTo() will create a method handle for-each call.

You can transform your code like that:

 private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
 private static final MethodType mt = MethodType.methodType(String.class, 
String.class);

 private static MethodHandle methodhandleLookup(Object receiver, String 
methodName) throws Throwable {
 return lookup.findVirtual(receiver.getClass(), methodName, mt);
 }

 private static String methodhandleInvoke(Object receiver, MethodHandle 
method) throws Throwable {
 return (String) method.invoke(receiver, methodhandle);
 }

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);
 }


Rémi

On 07/09/2011 12:01 PM, Jochen Theodorou wrote:
 Am 09.07.2011 10:48, schrieb Hiroshi Nakamura:
 Hello,

 I heard that jsr292 makes dynamic method lookupinvocation faster than
 reflection so I did some performance comparison against plain
 reflection. I'm sending this mail since the result looks strange to
 me.

 Code is here:
 https://raw.github.com/nahi/jsr292-sandbox/master/src/jp/gr/java_conf/jruby/MethodHandleTest.java
 lookup I don't know. I am not sure about the recent versions, I think
 the lookup is using the same core as Reflection plus additional
 checks. I don't expect that to be faster. It would be very nice though.

 The performance of the invocation cannot be meassured like you do it I
 think. The big pro comes from the ability to inline the method calls,
 but this is only present if you use the invokedynamic bytecode
 instruction. There is currently no way in Java to express invokedynamic.

 And a third point... even if there where invokedynamic used, I think in
 your case it would not really bring forth the real performance
 possibilities, since your receiver is changing all the time.

 But in general I must say, I would have expected the performance to be
 at least near Reflection as well. I mean the situation is for Reflection
 not all that better.

 bye blackdrag


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


Re: MethodHandle lookupinvocation performance

2011-07-09 Thread Rémi Forax
On 07/09/2011 12:21 PM, Rémi Forax wrote:
 You should avoid to create constants more than once.
 Also, bindTo() will create a method handle for-each call.

 You can transform your code like that:

   private static final MethodHandles.Lookup lookup = 
 MethodHandles.lookup();
   private static final MethodType mt = 
 MethodType.methodType(String.class, String.class);

   private static MethodHandle methodhandleLookup(Object receiver, String 
 methodName) throws Throwable {
   return lookup.findVirtual(receiver.getClass(), methodName, mt);
   }

   private static String methodhandleInvoke(Object receiver, MethodHandle 
 method) throws Throwable {
   return (String) method.invoke(receiver, methodhandle);
   }

 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);
  }



 Rémi

Rémi

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


Re: MethodHandle lookupinvocation performance

2011-07-09 Thread Hiroshi Nakamura
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* 10: 557.97 [msec], average:   5.58 [nsec]
methodhandle1 lookup+invoke * 10: 431.21 [msec], average:   4.31 [nsec]
methodhandle2 lookup* 10: 413.81 [msec], average:   4.14 [nsec]
methodhandle2 lookup+invoke * 10: 297.56 [msec], average:   2.98 [nsec]
reflectionlookup* 10:  99.52 [msec], average:   1.00 [nsec]
reflectionlookup+invoke * 10: 181.40 [msec], average:   1.81 [nsec]
-- 1
methodhandle1 lookup* 10: 192.42 [msec], average:   1.92 [nsec]
methodhandle1 lookup+invoke * 10: 289.65 [msec], average:   2.90 [nsec]
methodhandle2 lookup* 10: 267.24 [msec], average:   2.67 [nsec]
methodhandle2 lookup+invoke * 10: 327.26 [msec], average:   3.27 [nsec]
reflectionlookup* 10:  38.44 [msec], average:   0.38 [nsec]
reflectionlookup+invoke * 10:  65.53 [msec], average:   0.66 [nsec]
-- 2
methodhandle1 lookup* 10: 176.79 [msec], average:   1.77 [nsec]
methodhandle1 lookup+invoke * 10: 270.87 [msec], average:   2.71 [nsec]
methodhandle2 lookup* 10: 259.02 [msec], average:   2.59 [nsec]
methodhandle2 lookup+invoke * 10: 289.60 [msec], average:   2.90 [nsec]
reflectionlookup* 10:  31.77 [msec], average:   0.32 [nsec]
reflectionlookup+invoke * 10: 104.24 [msec], average:   1.04 [nsec]
-- 3
methodhandle1 lookup* 10: 220.45 [msec], average:   2.20 [nsec]
methodhandle1 lookup+invoke * 10: 282.01 [msec], average:   2.82 [nsec]
methodhandle2 lookup* 10: 265.23 [msec], average:   2.65 [nsec]
methodhandle2 lookup+invoke * 10: 299.53 [msec], average:   3.00 [nsec]
reflectionlookup* 10:  39.24 [msec], average:   0.39 [nsec]
reflectionlookup+invoke * 10:  70.76 [msec], average:   0.71 [nsec]
-- 4
methodhandle1 lookup* 10: 183.54 [msec], average:   1.84 [nsec]
methodhandle1 lookup+invoke * 10: 268.61 [msec], average:   2.69 [nsec]
methodhandle2 lookup* 10: 262.18 [msec], average:   2.62 [nsec]
methodhandle2 lookup+invoke * 10: 284.43 [msec], average:   2.84 [nsec]
reflectionlookup* 10:  28.34 [msec], average:   0.28 [nsec]
reflectionlookup+invoke * 10:  62.86 [msec], average:   0.63 [nsec]
-- 5
methodhandle1 lookup* 10: 182.89 [msec], average:   1.83 [nsec]
methodhandle1 lookup+invoke * 10: 260.14 [msec], average:   2.60 [nsec]
methodhandle2 lookup* 10: 262.31 [msec], average:   2.62 [nsec]
methodhandle2 lookup+invoke * 10: 284.80 [msec], average:   2.85 [nsec]
reflectionlookup* 10:  28.60 [msec], average:   0.29 [nsec]
reflectionlookup+invoke * 10:  67.08 [msec], average:   0.67 [nsec]
-- 6
methodhandle1 lookup* 10: 191.14 [msec], average:   1.91 [nsec]
methodhandle1 lookup+invoke * 10: 260.52 [msec], average:   2.61 [nsec]
methodhandle2 lookup* 10: 246.75 [msec], average:   2.47 [nsec]
methodhandle2 lookup+invoke * 10: 282.33 [msec], average:   2.82 [nsec]
reflectionlookup* 10:  28.98 [msec], average:   0.29 [nsec]
reflectionlookup+invoke * 10:  66.73 [msec], average:   0.67 

Re: MethodHandle lookupinvocation performance

2011-07-09 Thread Hiroshi Nakamura
Hello,

Thanks for you comments.

On Sat, Jul 9, 2011 at 19:01, Jochen Theodorou blackd...@gmx.org wrote:
 Code is here:
 https://raw.github.com/nahi/jsr292-sandbox/master/src/jp/gr/java_conf/jruby/MethodHandleTest.java

 lookup I don't know. I am not sure about the recent versions, I think
 the lookup is using the same core as Reflection plus additional
 checks. I don't expect that to be faster. It would be very nice though.

 The performance of the invocation cannot be meassured like you do it I
 think. The big pro comes from the ability to inline the method calls,
 but this is only present if you use the invokedynamic bytecode
 instruction. There is currently no way in Java to express invokedynamic.

Sure. I should have written it clearly. I heard from someone at Java
SE 7 launch event that reflection would get faster on Java SE 7 even
if you don't use dynamic language, so I wanted to measure the
MethodHandle perf without invokedynamic.

For invokedynamic, I did some (bogus, experimental, micro)benchmark
with current JRuby.
http://bit.ly/invokedynamic (Flash, Japanese)
Please see the circle at the right edge of 5 circles. Invokedynamic
support of JRuby is still experimental but it already outperforms
existing optimization code for some microbenchmarks. Great job,
Charles.

Disclaimer: I'm one of a JRuby committer :)

 And a third point... even if there where invokedynamic used, I think in
 your case it would not really bring forth the real performance
 possibilities, since your receiver is changing all the time.

Sure. JRuby's current invokedynamic code checks receiver type with the
test for guardWithTest if I understand correctly. Invokedynamic would
not bring perf gain for my sample MethodHandleTest, but if naive
MethodHandle invocation is slower than reflection, invokedynamic might
be the way I thought.

 But in general I must say, I would have expected the performance to be
 at least near Reflection as well. I mean the situation is for Reflection
 not all that better.

Agreed. I won't expect it to Java SE 7 GA though.

Regards,
// NaHi
___
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev


Re: MethodHandle lookupinvocation performance

2011-07-09 Thread Alexander Turner
Hi,

I am Alex Turner - I was working on a COBOL to JVM compiler and am now
helping with a Magik to JVM compiler. I thought I might just confirm
that invokeExact has proven a lt ot quicker than invoke in our tests.
We have also noticed that using a method adapter to convert argument
counts makes things a little slower (a few percent). But using an
adapter then invokeExact is much faster than using invoke.

My approach from here is to try very hard to avoid invoke and only use
it when there is no realistic chance of resolving an invokeExact for
more than one call.

Best wishes  - AJ

On 9 July 2011 14:08, Hiroshi Nakamura nakah...@gmail.com 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        * 10: 557.97 [msec], average:   5.58 [nsec]
 methodhandle1 lookup+invoke * 10: 431.21 [msec], average:   4.31 [nsec]
 methodhandle2 lookup        * 10: 413.81 [msec], average:   4.14 [nsec]
 methodhandle2 lookup+invoke * 10: 297.56 [msec], average:   2.98 [nsec]
 reflection    lookup        * 10:  99.52 [msec], average:   1.00 [nsec]
 reflection    lookup+invoke * 10: 181.40 [msec], average:   1.81 [nsec]
 -- 1
 methodhandle1 lookup        * 10: 192.42 [msec], average:   1.92 [nsec]
 methodhandle1 lookup+invoke * 10: 289.65 [msec], average:   2.90 [nsec]
 methodhandle2 lookup        * 10: 267.24 [msec], average:   2.67 [nsec]
 methodhandle2 lookup+invoke * 10: 327.26 [msec], average:   3.27 [nsec]
 reflection    lookup        * 10:  38.44 [msec], average:   0.38 [nsec]
 reflection    lookup+invoke * 10:  65.53 [msec], average:   0.66 [nsec]
 -- 2
 methodhandle1 lookup        * 10: 176.79 [msec], average:   1.77 [nsec]
 methodhandle1 lookup+invoke * 10: 270.87 [msec], average:   2.71 [nsec]
 methodhandle2 lookup        * 10: 259.02 [msec], average:   2.59 [nsec]
 methodhandle2 lookup+invoke * 10: 289.60 [msec], average:   2.90 [nsec]
 reflection    lookup        * 10:  31.77 [msec], average:   0.32 [nsec]
 reflection    lookup+invoke * 10: 104.24 [msec], average:   1.04 [nsec]
 -- 3
 methodhandle1 lookup        * 10: 220.45 [msec], average:   2.20 [nsec]
 methodhandle1 lookup+invoke * 10: 282.01 [msec], average:   2.82 [nsec]
 methodhandle2 lookup        * 10: 265.23 [msec], average:   2.65 [nsec]
 methodhandle2 lookup+invoke * 10: 299.53 [msec], average:   3.00 [nsec]
 reflection    lookup        * 10:  39.24 [msec], average:   0.39 [nsec]
 reflection    lookup+invoke * 10:  70.76 [msec], average:   0.71 [nsec]
 -- 4
 methodhandle1 lookup        * 10: 183.54 [msec], average:   1.84 [nsec]
 methodhandle1 lookup+invoke * 10: 268.61 [msec], average:   2.69 [nsec]
 methodhandle2 lookup        * 10: 262.18 [msec], average:   2.62 [nsec]
 methodhandle2 lookup+invoke * 10: 284.43 [msec], average:   2.84 [nsec]
 reflection    lookup        * 10:  28.34 [msec], average:   0.28 [nsec]
 reflection    lookup+invoke * 10:  62.86 [msec], average:   0.63 [nsec]
 -- 5
 methodhandle1 lookup        * 10: 182.89 [msec], average:   1.83 [nsec]
 methodhandle1 lookup+invoke * 10: 260.14 [msec], average:   2.60 [nsec]
 methodhandle2 lookup        * 10: 262.31 

Auto Reply: Re: MethodHandle lookupinvocation performance

2011-07-09 Thread bertrand . delsart
Sorry, I'm away till August 1st.

For urgent matters, please contact David.Therkelsen
___
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev


Re: MethodHandle lookupinvocation performance

2011-07-09 Thread Rémi Forax
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 Foraxfo...@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* 10: 557.97 [msec], average:   5.58 [nsec]
 methodhandle1 lookup+invoke * 10: 431.21 [msec], average:   4.31 [nsec]
 methodhandle2 lookup* 10: 413.81 [msec], average:   4.14 [nsec]
 methodhandle2 lookup+invoke * 10: 297.56 [msec], average:   2.98 [nsec]
 reflectionlookup* 10:  99.52 [msec], average:   1.00 [nsec]
 reflectionlookup+invoke * 10: 181.40 [msec], average:   1.81 [nsec]
 -- 1
 methodhandle1 lookup* 10: 192.42 [msec], average:   1.92 [nsec]
 methodhandle1 lookup+invoke * 10: 289.65 [msec], average:   2.90 [nsec]
 methodhandle2 lookup* 10: 267.24 [msec], average:   2.67 [nsec]
 methodhandle2 lookup+invoke * 10: 327.26 [msec], average:   3.27 [nsec]
 reflectionlookup* 10:  38.44 [msec], average:   0.38 [nsec]
 reflectionlookup+invoke * 10:  65.53 [msec], average:   0.66 [nsec]
 -- 2
 methodhandle1 lookup* 10: 176.79 [msec], average:   1.77 [nsec]
 methodhandle1 lookup+invoke * 10: 270.87 [msec], average:   2.71 [nsec]
 methodhandle2 lookup* 10: 259.02 [msec], average:   2.59 [nsec]
 methodhandle2 lookup+invoke * 10: 289.60 [msec], average:   2.90 [nsec]
 reflectionlookup* 10:  31.77 [msec], average:   0.32 [nsec]
 reflectionlookup+invoke * 10: 104.24 [msec], average:   1.04 [nsec]
 -- 3
 methodhandle1 lookup* 10: 220.45 [msec], average:   2.20 [nsec]
 methodhandle1 lookup+invoke * 10: 282.01 [msec], average:   2.82 [nsec]
 methodhandle2 lookup* 10: 265.23 [msec], average:   2.65 [nsec]
 methodhandle2 lookup+invoke * 10: 299.53 [msec], average:   3.00 [nsec]
 reflectionlookup* 10:  39.24 [msec], average:   0.39 [nsec]
 reflectionlookup+invoke * 10:  70.76 [msec], average:   0.71 [nsec]
 -- 4
 methodhandle1 lookup