Created
February 28, 2023 08:36
-
-
Save lexakimov/8568c49399701ad9f476a4d6035d45d6 to your computer and use it in GitHub Desktop.
lambdametafactory
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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