/* * Quasar: lightweight threads and actors for the JVM. * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 3.0 * as published by the Free Software Foundation. */ package co.paralleluniverse.data.record; import co.paralleluniverse.data.record.Field; import co.paralleluniverse.data.record.Record; import co.paralleluniverse.data.record.RecordType; import java.util.concurrent.ThreadLocalRandom; import org.openjdk.jmh.Main; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.Level; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; @State(Scope.Thread) public class RecordJMHBenchmark { /* * See: * http://psy-lob-saw.blogspot.co.il/2013/04/writing-java-micro-benchmarks-with-jmh.html * http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/ */ private static final String BENCHMARK = RecordJMHBenchmark.class.getName() + ".*"; public static void main(String[] args) throws Exception { // Main.main(new String[]{"-usage"}); Main.main(buildArguments(BENCHMARK, 5, 5000, 1)); } private static String[] buildArguments(String className, int nRuns, int runForMilliseconds, int nThreads) { return new String[]{className, "-f", "1", "-i", "" + nRuns, "-r", runForMilliseconds + "ms", "-t", "" + nThreads, "-w", "5000ms", "-wi", "3", "-prof", "stack,hs_rt,gc" }; } public static class Foo { public int a; public double b; public long c; } public static class Foo1 extends Foo { } public static class Foo2 extends Foo { } public static class Foo3 extends Foo { } public static class Foo4 extends Foo { } static final RecordType<Foo> rt = RecordType.newType(Foo.class); static final Field.IntField<Foo> $a = rt.intField("a"); static final Field.DoubleField<Foo> $b = rt.doubleField("b"); static final Field.LongField<Foo> $c = rt.longField("c"); ThreadLocalRandom r; Foo x; Record<Foo> simple; Record<Foo> dynamicMethodHandle; Record<Foo> dynamicReflection; Record<Foo> dynamicUnsafe; Record<Foo> dynamicGeneration; @Setup(Level.Iteration) public void init() { r = ThreadLocalRandom.current(); x = new Foo(); simple = rt.newInstance(); dynamicMethodHandle = rt.wrap(new Foo1(), RecordType.Mode.METHOD_HANDLE); dynamicReflection = rt.wrap(new Foo2(), RecordType.Mode.REFLECTION); dynamicUnsafe = rt.wrap(new Foo3(), RecordType.Mode.UNSAFE); dynamicGeneration = rt.wrap(new Foo4(), RecordType.Mode.GENERATION); } @Benchmark public Object timeSimple() { return foo(simple); } @Benchmark public Object timeDynamicMethodHandle() { return foo(dynamicMethodHandle); } @Benchmark public Object timeDynamicReflection() { return foo(dynamicReflection); } @Benchmark public Object timeDynamicUnsafe() { return foo(dynamicUnsafe); } @Benchmark public Object timeDynamicGeneration() { return foo(dynamicGeneration); } private Object foo(Record<Foo> x) { x.set($a, (int) x.get($c) + r.nextInt(100)); x.set($b, x.get($a) + r.nextDouble(100)); x.set($c, (long) x.get($b) + r.nextLong(200)); return x; } @Benchmark public Object timePojo() { x.a = (int) x.c + r.nextInt(100); x.b = x.a + r.nextDouble(100); x.c = (long) x.b + r.nextLong(200); return x; } }