Skip to content

Instantly share code, notes, and snippets.

@lucamolteni
Created March 11, 2021 17:19
Show Gist options
  • Save lucamolteni/f4f2f79d01097ef309990f395065e706 to your computer and use it in GitHub Desktop.
Save lucamolteni/f4f2f79d01097ef309990f395065e706 to your computer and use it in GitHub Desktop.
package org.example;
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.concurrent.TimeUnit;
import java.util.function.IntSupplier;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5)
@Measurement(iterations = 5)
@Fork(1)
public class InvokeInterfaceCacheBench {
@Param({"4"})
public int types;
private IntSupplier[] typesArray;
private int next = 0;
private int tokens;
@Setup
public void init(Blackhole bh) throws Throwable {
typesArray = new IntSupplier[types];
for (int i = 0; i < types; i++) {
typesArray[i] = create(i);
if (i > 0) {
if (typesArray[i - 1].getClass().equals(typesArray[i].getClass())) {
System.err.println("We're not producing different lambda classes here!");
System.exit(1);
}
}
}
}
public IntSupplier create(int i) throws Throwable {
final Integer integer = i;
// return integer::intValue;
Method reflectionMethod = Integer.class.getMethod("intValue");
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle handle = lookup.unreflect(reflectionMethod);
CallSite callSite = LambdaMetafactory.metafactory(
// method handle lookup
lookup,
// name of the method defined in the target functional interface
"getAsInt",
// type to be implemented and captured objects
// in this case the String instance to be trimmed is captured
MethodType.methodType(IntSupplier.class, Integer.class),
MethodType.methodType(int.class),
handle,
MethodType.methodType(int.class));
IntSupplier lambda = (IntSupplier) callSite.getTarget().bindTo(integer).invoke();
return lambda;
}
private IntSupplier next() {
final IntSupplier intConsumer = typesArray[next];
if (next == typesArray.length - 1) {
next = 0;
} else {
next++;
}
return intConsumer;
}
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
@Benchmark
public int call() {
final IntSupplier next = next();
return next.getAsInt();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment