package org.gololang.microbenchmarks.arithmetic; import org.gololang.microbenchmarks.support.CodeLoader; import org.openjdk.jmh.annotations.*; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.Random; import java.util.concurrent.TimeUnit; import static java.lang.invoke.MethodType.genericMethodType; import static java.lang.invoke.MethodType.methodType; @BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MILLISECONDS) public class CostOfSumMicroBenchmark { public static long sum(long x, long y) { return x + y; } public static Object boxed_sum(Object x, Object y) { return (Long) x + (Long) y; } public static Object boxed_sum_with_constant(Object x) { return (Long) x + 10L; } @State(Scope.Thread) static public class DataState { long x; long y; @Setup(Level.Iteration) public void setup() { Random rand = new Random(); x = (long) rand.nextInt(); y = (long) rand.nextInt(); } } @State(Scope.Thread) static public class JavaState { MethodHandle sumHandle; MethodHandle boxedSumHandle; MethodHandle boxedSumWithConstantHandle; @Setup(Level.Trial) public void setup() { try { MethodHandles.Lookup lookup = MethodHandles.lookup(); sumHandle = lookup.findStatic(CostOfSumMicroBenchmark.class, "sum", methodType(long.class, long.class, long.class)); boxedSumHandle = lookup.findStatic(CostOfSumMicroBenchmark.class, "boxed_sum", genericMethodType(2)); boxedSumWithConstantHandle = lookup.findStatic(CostOfSumMicroBenchmark.class, "boxed_sum_with_constant", genericMethodType(1)); } catch (NoSuchMethodException | IllegalAccessException e) { throw new AssertionError(e); } } } @State(Scope.Thread) static public class GoloState { MethodHandle sumHandle; MethodHandle sumWithConstantHandle; MethodHandle sumOfConstantsHandle; @Setup(Level.Trial) public void setup() { sumHandle = new CodeLoader().golo("arithmetic", "sum", 2); sumWithConstantHandle = new CodeLoader().golo("arithmetic", "sum_with_constant", 1); sumOfConstantsHandle = new CodeLoader().golo("arithmetic", "sum_of_constants", 0); } } @State(Scope.Thread) static public class GroovyState { MethodHandle sumHandle; MethodHandle sumWithConstantHandle; MethodHandle sumOfConstantsHandle; MethodHandle fastSumHandle; MethodHandle fastestSumHandle; @Setup(Level.Trial) public void setup() { sumHandle = new CodeLoader().groovy("arithmetic", "sum", genericMethodType(2)); sumWithConstantHandle = new CodeLoader().groovy("arithmetic", "sum_with_constant", genericMethodType(1)); sumOfConstantsHandle = new CodeLoader().groovy("arithmetic", "sum_of_constants", genericMethodType(0)); fastSumHandle = new CodeLoader().groovy("arithmetic", "fast_sum", methodType(long.class, long.class, long.class)); fastestSumHandle = new CodeLoader().groovy("arithmetic", "fastest_sum", methodType(long.class, long.class, long.class)); } } @State(Scope.Thread) static public class GroovyIndyState { MethodHandle sumHandle; MethodHandle sumWithConstantHandle; MethodHandle sumOfConstantsHandle; MethodHandle fastSumHandle; MethodHandle fastestSumHandle; @Setup(Level.Trial) public void setup() { sumWithConstantHandle = new CodeLoader().groovy("arithmetic", "sum_with_constant", genericMethodType(1)); sumOfConstantsHandle = new CodeLoader().groovy("arithmetic", "sum_of_constants", genericMethodType(0)); sumHandle = new CodeLoader().groovy_indy("arithmetic", "sum", genericMethodType(2)); fastSumHandle = new CodeLoader().groovy_indy("arithmetic", "fast_sum", methodType(long.class, long.class, long.class)); fastestSumHandle = new CodeLoader().groovy_indy("arithmetic", "fastest_sum", methodType(long.class, long.class, long.class)); } } @Benchmark public Object baseline_java(DataState dataState, JavaState javaState) throws Throwable { return javaState.sumHandle.invoke(dataState.x, dataState.y); } @Benchmark public Object baseline_return_value(DataState dataState) { return dataState.x; } @Benchmark public Object baseline_java_boxed(DataState dataState, JavaState javaState) throws Throwable { return javaState.boxedSumHandle.invoke(dataState.x, dataState.y); } @Benchmark public Object baseline_java_boxed_with_constant(DataState dataState, JavaState javaState) throws Throwable { return javaState.boxedSumWithConstantHandle.invoke(dataState.x); } @Benchmark public Object golo_sum(DataState dataState, GoloState goloState) throws Throwable { return goloState.sumHandle.invoke(dataState.x, dataState.y); } @Benchmark public Object golo_sum_with_constant(DataState dataState, GoloState goloState) throws Throwable { return goloState.sumWithConstantHandle.invoke(dataState.x); } @Benchmark public Object golo_sum_of_constants(DataState dataState, GoloState goloState) throws Throwable { return goloState.sumOfConstantsHandle.invoke(); } @Benchmark public Object groovy_sum(DataState dataState, GroovyState groovyState) throws Throwable { return groovyState.sumHandle.invoke(dataState.x, dataState.y); } @Benchmark public Object groovy_sum_with_constant(DataState dataState, GroovyState groovyState) throws Throwable { return groovyState.sumWithConstantHandle.invoke(dataState.x); } @Benchmark public Object groovy_sum_of_constants(GroovyState groovyState) throws Throwable { return groovyState.sumOfConstantsHandle.invoke(); } @Benchmark public Object groovy_sum_fast(DataState dataState, GroovyState groovyState) throws Throwable { return groovyState.fastSumHandle.invoke(dataState.x, dataState.y); } @Benchmark public Object groovy_sum_fastest(DataState dataState, GroovyState groovyState) throws Throwable { return groovyState.fastestSumHandle.invoke(dataState.x, dataState.y); } @Benchmark public Object groovy_sum_indy(DataState dataState, GroovyIndyState groovyState) throws Throwable { return groovyState.sumHandle.invoke(dataState.x, dataState.y); } @Benchmark public Object groovy_sum_indy_sum_with_constant(DataState dataState, GroovyIndyState groovyState) throws Throwable { return groovyState.sumWithConstantHandle.invoke(dataState.x); } @Benchmark public Object groovy_sum_indy_sum_of_constants(GroovyIndyState groovyState) throws Throwable { return groovyState.sumOfConstantsHandle.invoke(); } @Benchmark public Object groovy_sum_indy_fast(DataState dataState, GroovyIndyState groovyState) throws Throwable { return groovyState.fastSumHandle.invoke(dataState.x, dataState.y); } @Benchmark public Object groovy_sum_indy_fastest(DataState dataState, GroovyIndyState groovyState) throws Throwable { return groovyState.fastestSumHandle.invoke(dataState.x, dataState.y); } }