performance issue: 7023639: JSR 292 method handle invocation needs a fast path for compiled code

Rémi Forax forax at univ-mlv.fr
Tue Mar 1 17:42:23 PST 2011


John,
There is also another optimization that should be done.
Once all the optimizations that you have listed will be done,
the code will be as fast (or as slow but I'm optimistic by nature) as 
using inner classes.

Let say we have the following code:

public static void main(String[] args) {
     Mapper<Object, Object> mapper1 = #{ o -> o };
     Mapper<Object, Object> mapper2 = #{ o -> o };
     Mapper<Object, Object> mapper3 = #{ o -> o };

     ArrayList<Object> list = new ArrayList<Object>();
     for(int i=0; i<1000000; i++) {
       list.add("foo");
     }

     for(int i=0; i<200; i++) {
       test(mapper1, mapper2, mapper3, list);
     }

     System.out.println(list.size());
   }

   private static void test(Mapper<Object, Object> mapper1, 
Mapper<Object, Object> mapper2, Mapper<Object, Object> mapper3, 
ArrayList<Object> list) {
     bar(list, mapper1);
     bar(list, mapper2);
     bar(list, mapper3);
   }

   private static <E> void bar(ArrayList<E> list, Mapper<E, E> mapper) {
     int size = list.size();
     for(int i=0; i<size; i++) {
       list.set(i, mapper.apply(list.get(i)));
     }
   }

If lambdas are implemented using inner-classes, mapper.apply is megamorphic
and a vtable dispatch is done.

If lambda are implemented using method-handles, mapper.apply will 
directly call
the underlying method handle (because there is only one implementation 
of Mapper).

Here is test is not a hot method, so bar will be not be inlined in test
and specialized for each lambda.
The problem is how to tell the JIT that test should be inlined.

One solution is to go backward i.e detect that mapper.apply is a method 
handle call
so consider that all callers of bar should be compiled even if they are 
not hot but only warm.

If someone implement that before the release of JDK 8, I will praise him 
every night.

Rémi


On 03/02/2011 01:42 AM, John Rose wrote:
> It took us years to learn to optimize calls to Java methods.  Now we are beginning to learn how to optimize uses of method handles.  This new learning curve won't take as long as the old one, since we can reuse our existing knowledge.  But it won't be instantaneous either.  I expect both JDK 7 and JDK 8 to include important performance improvements to method handles and invokedynamic.
>
> To help us track our progress and manage our tuning work, we will (from time to time) file issues having to do with JSR 292 performance.
>
> Issue 7023639 applies to people who are using method handles as function pointers for Java.  If this affects your use of 292, please let us know.
>
> Other issues likely to arise have to do with performance disparities between method handles obtained from MethodHandles.Lookup and the corresponding bytecoded and reflective operations.
>
> Onward!
>
> -- John Rose
>
> P.S. Here's the bug text:
>
> 7023639 JSR 292 method handle invocation needs a fast path for compiled code
>
> This is a tracking issue for calls to non-constant method handles to and from "hot" compiled code.
>
> Internally to the JVM, method handle argument list transformations are implemented on the interpreter stack.  This means that when compiled code invokes a method handle with argument transforms, it goes through a C2I adapter, transforms the argument list in interpreted format, and then (presumably) goes through an I2C adapter.
>
> At least the most important transforms should go through customized code.  These include:
> - direct access (no transforms)
> - receiver binding (the bindTo transformation)
> - trivial asType transformations
> - invokeGeneric (argument and return value conversions to and from Object)
>
> Probably all of the core transforms on MethodHandle virtual methods (not necessarily MethodHandles static methods) should get favorable treatment for compiled-to-compiled calls.
>
> An important customer is Project Lambda, which should be using method handles in preference to anonymous classes.  Getting the above paths right for compiled code will enable this choice.
>
> Note that this bug does not apply to users invokedynamic, since method handles at invokedynamic call sites are routinely inlined into optimized code.
>
> _______________________________________________
> mlvm-dev mailing list
> mlvm-dev at openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev



More information about the mlvm-dev mailing list