Created
February 13, 2023 21:50
-
-
Save franz1981/4234195ca0168f3833023b610d91ddff to your computer and use it in GitHub Desktop.
This file contains 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
package red.hat.puzzles.loom; | |
import java.lang.invoke.MethodHandle; | |
import java.lang.invoke.MethodHandles; | |
import java.lang.reflect.InvocationTargetException; | |
import java.lang.reflect.Method; | |
import java.util.concurrent.TimeUnit; | |
import org.openjdk.jmh.annotations.Benchmark; | |
import org.openjdk.jmh.annotations.BenchmarkMode; | |
import org.openjdk.jmh.annotations.Fork; | |
import org.openjdk.jmh.annotations.Measurement; | |
import org.openjdk.jmh.annotations.Mode; | |
import org.openjdk.jmh.annotations.OutputTimeUnit; | |
import org.openjdk.jmh.annotations.Scope; | |
import org.openjdk.jmh.annotations.State; | |
import org.openjdk.jmh.annotations.Warmup; | |
@State(Scope.Benchmark) | |
@BenchmarkMode(Mode.AverageTime) | |
@OutputTimeUnit(TimeUnit.NANOSECONDS) | |
@Measurement(iterations = 5, time = 100, timeUnit = TimeUnit.MILLISECONDS) | |
@Warmup(iterations = 10, time = 100, timeUnit = TimeUnit.MILLISECONDS) | |
@Fork(2) | |
public class VirtualThreadReflectionBenchmark { | |
private static final class Dummy { | |
private static Thread currentCarrierThread() { | |
return Thread.currentThread(); | |
} | |
} | |
private static final Method CURRENT_CARRIER_METHOD = currentCarrierThreadMethod(); | |
private static final Method DUMMY_CURRENT_CARRIER_METHOD = dummyCurrentCarrierThreadMethod(); | |
private static final MethodHandle CURRENT_CARRIER_MH = currentCarrierThreadMH(); | |
private static Method dummyCurrentCarrierThreadMethod() { | |
try { | |
Method currentCarrierThread = Dummy.class.getDeclaredMethod("currentCarrierThread"); | |
currentCarrierThread.setAccessible(true); | |
Thread dummy = (Thread) currentCarrierThread.invoke(null); | |
return currentCarrierThread; | |
} catch (Throwable e) { | |
e.printStackTrace(); | |
return null; | |
} | |
} | |
private static Method currentCarrierThreadMethod() { | |
try { | |
Method currentCarrierThread = Thread.class.getDeclaredMethod("currentCarrierThread"); | |
currentCarrierThread.setAccessible(true); | |
// this is to check if --enable-preview for Java 19 is correctly set | |
Thread dummy = (Thread) currentCarrierThread.invoke(null); | |
return currentCarrierThread; | |
} catch (Throwable e) { | |
e.printStackTrace(); | |
return null; | |
} | |
} | |
private static MethodHandle currentCarrierThreadMH() { | |
try { | |
MethodHandle mh = MethodHandles.lookup().unreflect(currentCarrierThreadMethod()); | |
Thread t = (Thread) mh.invokeExact(); | |
return mh; | |
} catch (Throwable e) { | |
e.printStackTrace(); | |
return null; | |
} | |
} | |
private static Thread currentCarrierThread() { | |
try { | |
return (Thread) CURRENT_CARRIER_METHOD.invoke(null); | |
} catch (IllegalAccessException e) { | |
throw new RuntimeException(e); | |
} catch (InvocationTargetException e) { | |
throw new RuntimeException(e); | |
} | |
} | |
private static Thread dummyCurrentCarrierThread() { | |
try { | |
return (Thread) DUMMY_CURRENT_CARRIER_METHOD.invoke(null); | |
} catch (IllegalAccessException e) { | |
throw new RuntimeException(e); | |
} catch (InvocationTargetException e) { | |
throw new RuntimeException(e); | |
} | |
} | |
private static Thread currentCarrierThreadInvokeExact() { | |
try { | |
// NOT USING primitive on purpose :"( Netty 4.1 is Java 1.6 sigh! | |
return (Thread) CURRENT_CARRIER_MH.invokeExact(); | |
} catch (Throwable e) { | |
throw new RuntimeException(e); | |
} | |
} | |
@Benchmark | |
public Thread reflectiveCurrentCarrierThread() { | |
return currentCarrierThread(); | |
} | |
@Benchmark | |
public Thread mhCurrentCarrierThread() { | |
return currentCarrierThreadInvokeExact(); | |
} | |
@Benchmark | |
public Thread reflectiveDummyCurrentCarrierThread() { | |
return dummyCurrentCarrierThread(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Env:
Results:
Profiling reveal that
reflectiveCurrentCarrierThread
is performing some additional ops:while the
MethodHandle
version:and finally, the dummy version: