Skip to content

Instantly share code, notes, and snippets.

@schmitch
Last active December 14, 2016 08:39
Show Gist options
  • Save schmitch/df9596699716788d37a52e2ceed2c3a2 to your computer and use it in GitHub Desktop.
Save schmitch/df9596699716788d37a52e2ceed2c3a2 to your computer and use it in GitHub Desktop.
Main.java perf problems
/*
Outcome: c.schmitt - MacBook Pro (Retina, 15", Ende 2013) - macOS 10.12.1
sbt "jmh:run -i 10 -wi 10 -f1 -t1"
[info] Benchmark Mode Cnt Score Error Units
[info] Main.testMethod thrpt 10 19538048,171 ± 2224217,470 ops/s
[info] Main.testMethodHandleIntSupplierUnreflect thrpt 10 6735285,753 ± 281407,613 ops/s
[info] Main.testMethodHandleUnreflect thrpt 10 28706699,796 ± 755897,511 ops/s
[info] Main.testMethodHandleUnreflectListSize thrpt 10 20084867,818 ± 449023,818 ops/s
[info] Main.testMethodHandleUnreflectSimple thrpt 10 28637750,180 ± 685004,308 ops/s
[info] Main.testMethodHandleUnreflectSimpleArguments thrpt 10 5267296,404 ± 71604,568 ops/s
[info] Main.testMethodHandleUnreflectSimpleExact thrpt 10 28942872,351 ± 217140,908 ops/s
[info] Main.testMethodHandleVirtual thrpt 10 28358600,382 ± 597161,522 ops/s
[info] Main.testMethodHandleVirtualArguments thrpt 10 5308500,677 ± 236293,160 ops/s
*/
package bla;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.function.IntSupplier;
@State(value = Scope.Benchmark)
public class Main {
private static final MethodHandle handle1;
private static final MethodHandle handle2;
private static final Method method;
private static final Function<Integer, String> f = (Integer s) -> "hello " + s;
private static final IntSupplier is = () -> 1;
public static Method fun(Class<?> actionFunction) {
Method actionMethod = null;
for (Method m : actionFunction.getMethods()) {
// Here I assume that we are always passing a `actionFunction` type that:
// 1) defines exactly one abstract method, and
// 2) the abstract method is the method that we want to invoke.
// This works fine with the current implementation of `PathPatternMatcher`, but I wouldn't be
// surprised if it breaks in the future, which is why this comment exists.
// Also, the former implementation (which was checking for the first non default method), was
// not working when using a `java.util.function.Function` type (Function.identity was being
// returned, instead of Function.apply).
if (Modifier.isAbstract(m.getModifiers())) {
actionMethod = m;
}
}
return actionMethod;
}
static {
try {
handle1 = t1(f, Function.class);
handle2 = t2(is, IntSupplier.class);
method = fun(Function.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static <T> MethodHandle t1(T action, Class<?> actionFunction) {
try {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
return lookup.findVirtual(actionFunction, "apply",
MethodType.methodType(Object.class, Object.class));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static <T> MethodHandle t2(T action, Class<?> actionFunction) {
try {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
return lookup.unreflect(fun(actionFunction));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Benchmark
public void testMethod() throws Throwable {
String ignored = (String) method.invoke(f, 1000);
}
@Benchmark
public void testMethodHandleVirtualArguments() throws Throwable {
String ignored = (String) ((Object) handle1.invokeWithArguments(f, (Object) 1000));
}
@Benchmark
public void testMethodHandleVirtual() throws Throwable {
String ignored = (String) ((Object) handle1.invoke(f, (Object) 1000));
}
@Benchmark
public void testMethodHandleUnreflectListSize() throws Throwable {
List<Object> li = Collections.singletonList(1000);
int s = li.size();
if (s == 0) {
String ignored = (String) handle1.invoke(f);
} else if (s == 1) {
String ignored = (String) handle1.invoke(f, li.get(0));
} else if (s == 2) {
String ignored = (String) handle1.invoke(f, li.get(0), li.get(1));
} else if (s == 3) {
String ignored = (String) handle1.invoke(f, li.get(0), li.get(1), li.get(2));
} else {
ArrayList<Object> al = new ArrayList<>(li);
al.add(0, f);
String ignored = (String) handle1.invokeWithArguments(al);
}
}
@Benchmark
public void testMethodHandleUnreflectSimple() throws Throwable {
String ignored = (String) ((Object) handle1.invoke(f, (Object) 1000));
}
@Benchmark
public void testMethodHandleUnreflectSimpleExact() throws Throwable {
String ignored = (String) ((Object) handle1.invokeExact(f, (Object) 1000));
}
@Benchmark
public void testMethodHandleUnreflectSimpleArguments() throws Throwable {
String ignored = (String) handle1.invokeWithArguments(f, (Object) 1000);
}
@Benchmark
public void testMethodHandleUnreflect() throws Throwable {
String ignored = (String) ((Object) handle1.invokeExact(f, (Object) 1000));
}
@Benchmark
public void testMethodHandleIntSupplierUnreflect() throws Throwable {
int ignored = (int) handle2.invokeWithArguments(is);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment