Why LambdaMetaFactory is taking more time to execute a method in Java?

56 views Asked by At

I'm trying to do performance testing of the below mentioned code with three scenarios by logging the execution time of a getName method of a Person Class.

  1. LambdaMetaFactory
  2. Direct Access
  3. Reflection

Ideally, reflection should take more time to execute than the LambdaMetaFactory. But, my output is surprising as shown below :

Lambda Exec Time :: 3510309 ns
Direct Exec Time :: 2701586 ns
Reflection Exec Time :: 10 ns 

Are there any issues in the code?

My code:

package com.jpmc.util.test.reflection;

import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;

public class PerformanceTest {

    public static void main(String args[]) throws Throwable {

        //LambdaMetaFactory
        var lookup = MethodHandles.lookup();
        var interfaceMethodName = "invoke";
        var factoryType = MethodType.methodType(GetterFunction.class);
        var interfaceMethodType = MethodType.methodType(Object.class,Object.class);
        var implementation = lookup.findVirtual(Person.class,"getName",MethodType.methodType(String.class));
        var dynamicMethodType = MethodType.methodType(String.class,Person.class);

        var factory = LambdaMetafactory.metafactory(lookup,
                interfaceMethodName,
                factoryType,
                interfaceMethodType,
                implementation,
                dynamicMethodType);

        var getterFunction = (GetterFunction<Person,String>) factory.getTarget().invoke();
        Person  person = new Person("Joe");
        long startTime = System.nanoTime();
        int runs = 100000;
        for (int i = 0; i < runs; i++) {
            getterFunction.invoke(person);
        }
        long endTime = System.nanoTime();
        System.out.println( "Lambda Exec Time :: "+ (endTime-startTime) + " ns");

       //Direct Access
     
        {
            long start = System.nanoTime();
            for (int i = 0; i < runs; i++)
                //direct access
                person.getName();
            long time = System.nanoTime() - start;
            System.out.println( "Direct Exec Time :: "+ time + " ns");
        }

        //Reflection
        Method getNameMethod = Person.class.getMethod("getName");
        {
            long start = System.currentTimeMillis();
            for (int i = 0; i < runs; i++)
                //reflection access
                getNameMethod.invoke(person);
            long time = System.currentTimeMillis() - start;
            System.out.println( "Reflection Exec Time :: "+ time+ " ns");
        }
    }

}


@FunctionalInterface
interface GetterFunction<T,U> {
    U  invoke (T instance);
}

 class Person {
        String name;
        public Person(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }

     @Override
     public String toString() {
         return name;
     }
 }

Edited

Have understood to use benchmarking. But, is it mandatory to use benchmarking for LambdaMetaFactory to log the execution time ? Just want to get the execution time of all approaches (LambdaMetaFactory, Reflection, DirectAccess) via simple Java code.

What are the results unexpected and what changes do I need to make for desired results?

0

There are 0 answers