Skip to content

Instantly share code, notes, and snippets.

@lexakimov
Created February 28, 2023 08:36
Show Gist options
  • Select an option

  • Save lexakimov/8568c49399701ad9f476a4d6035d45d6 to your computer and use it in GitHub Desktop.

Select an option

Save lexakimov/8568c49399701ad9f476a4d6035d45d6 to your computer and use it in GitHub Desktop.
lambdametafactory
import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.function.Function;
public class TestMethodPerf {
private static final int CALLS_PER_ITERATION = 50_000_000;
private static final int WARM_UP_ITERATIONS = 0; // 2
//direct: 0,055776439 s 0,034841811 s
//mh: 2,943104902 s 2,965625030 s
//lambda: 0,042090928 s 0,011553449 s
//reference: 0,015642675 s 2,449855239 s
//reflection: 0,969880611 s 0,983534769 s
public static void main(String... args) throws Throwable {
var book = new Book();
book.setTitle("kek");
book.setYear(2);
MethodHandles.Lookup lookup = MethodHandles.lookup();
// lookup.findGetter(C.class, "f", FT.class)
MethodType function = MethodType.methodType(Function.class);
MethodType functionSignature = MethodType.methodType(Object.class, Object.class);
MethodHandle getter = lookup.findVirtual(Book.class, "getYear", MethodType.methodType(int.class));
MethodType getterSignature = MethodType.methodType(int.class, Book.class);
CallSite site = LambdaMetafactory.metafactory(lookup, "apply", function, functionSignature, getter, getterSignature);
Function<Book, Integer> lambda = (Function<Book, Integer>) site.getTarget().invokeExact();
Method reflected = Book.class.getDeclaredMethod("getYear");
MethodHandle mh = lookup.findVirtual(Book.class, "getYear", MethodType.methodType(int.class));
Function<Book, Integer> reference = Book::getYear;
for (int i = 0; i < WARM_UP_ITERATIONS; i++) {
testDirect(book);
testMH(book, mh);
testLambda(book, lambda);
testLambda(book, reference);
testReflection(book, reflected);
}
long t0 = System.nanoTime();
testDirect(book);
long t1 = System.nanoTime();
testReflection(book, reflected);
long t2 = System.nanoTime();
testMH(book, mh);
long t3 = System.nanoTime();
testLambda(book, reference);
long t4 = System.nanoTime();
testLambda(book, lambda);
long t5 = System.nanoTime();
System.out.printf(" direct (ms): %10.3f%n", (t1 - t0) * 1e-6);
System.out.printf("reflection (ms): %10.3f%n", (t2 - t1) * 1e-6);
System.out.printf(" mh (ms): %10.3f%n", (t3 - t2) * 1e-6);
System.out.printf(" reference (ms): %10.3f%n", (t4 - t3) * 1e-6);
System.out.printf(" lambda (ms): %10.3f%n", (t5 - t4) * 1e-6);
}
private static long testDirect(Book book) {
long j = 0;
for (int i = 0; i < CALLS_PER_ITERATION; i++) {
j += book.getYear();
}
return j;
}
private static long testMH(Book book, MethodHandle mh) throws Throwable {
long j = 0;
for (int i = 0; i < CALLS_PER_ITERATION; i++) {
j += (long) mh.invoke(book); //invokeExact
}
return j;
}
private static long testLambda(Book book, Function<Book, Integer> accessor) {
long j = 0;
for (int i = 0; i < CALLS_PER_ITERATION; i++) {
j += accessor.apply(book);
}
return j;
}
private static long testReflection(Book book, Method mh) throws Throwable {
long j = 0;
for (int i = 0; i < CALLS_PER_ITERATION; i++) {
j += (Integer) mh.invoke(book);
}
return j;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment