# HG changeset patch # User shade # Date 1511362328 -3600 # Node ID f5ac05188aa1cd6116f1cfab67e7e6875e17d32e # Parent 0cb1442be9d6e079b3e6d1bf7f65f3e0f537a6cd Autogenerate class roots tests diff -r 0cb1442be9d6 -r f5ac05188aa1 pom.xml --- a/pom.xml Thu Oct 26 17:04:09 2017 +0200 +++ b/pom.xml Wed Nov 22 15:52:08 2017 +0100 @@ -66,6 +66,11 @@ ${jmh.version} provided + + org.ow2.asm + asm + 5.0.3 + diff -r 0cb1442be9d6 -r f5ac05188aa1 src/main/java/org/openjdk/gcbench/roots/ClassGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/org/openjdk/gcbench/roots/ClassGenerator.java Wed Nov 22 15:52:08 2017 +0100 @@ -0,0 +1,75 @@ +package org.openjdk.gcbench.roots; + +import org.objectweb.asm.*; + +import java.net.URL; +import java.net.URLClassLoader; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.objectweb.asm.Opcodes.*; + +public class ClassGenerator { + + private static final int CLASSFILE_VERSION = 50; + + private static final AtomicInteger idx = new AtomicInteger(); + + + public static Class generate(ByteClassLoader cl) throws Exception { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + + String name = "Class" + idx.incrementAndGet(); + + cw.visit(CLASSFILE_VERSION, + ACC_PUBLIC + ACC_SUPER, + name, + null, + Type.getInternalName(Object.class), + new String[0]); + + cw.visitSource(name + ".java", null); + + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + cw.visitField(ACC_STATIC, "ref", "Ljava/lang/Object;", "Ljava/lang/Object;", null); + + cw.visitEnd(); + + cl.put(name, cw.toByteArray()); + return cl.findClass(name); + } + + public static class ByteClassLoader extends URLClassLoader { + private final Map customClasses; + + public ByteClassLoader() { + super(new URL[] {}); + customClasses = new ConcurrentHashMap<>(); + } + + @Override + protected Class findClass(final String name) throws ClassNotFoundException { + if (customClasses.containsKey(name)) { + byte[] bs = customClasses.get(name); + return defineClass(name, bs, 0, bs.length); + } + return super.findClass(name); + } + + public void put(String name, byte[] bytes) { + customClasses.put(name, bytes); + } + } + +} \ No newline at end of file diff -r 0cb1442be9d6 -r f5ac05188aa1 src/main/java/org/openjdk/gcbench/roots/Classes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/org/openjdk/gcbench/roots/Classes.java Wed Nov 22 15:52:08 2017 +0100 @@ -0,0 +1,44 @@ +package org.openjdk.gcbench.roots; + +import org.openjdk.jmh.annotations.*; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Fork(1) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Threads(Threads.MAX) +@State(Scope.Benchmark) +public class Classes { + + @Param({"1", "10", "1000", "10000", "100000"}) + int classes; + + @Param({"1", "10", "100", "1000"}) + int classloaders; + + Class[] arr; + ClassGenerator.ByteClassLoader[] cls; + + @Setup + public void setup() throws Exception { + arr = new Class[classes]; + cls = new ClassGenerator.ByteClassLoader[classloaders]; + int classesPerCl = classes / classloaders; + for (int c = 0; c < classloaders; c++) { + cls[c] = new ClassGenerator.ByteClassLoader(); + for (int v = 0; v < classesPerCl; v++) { + arr[c*classesPerCl + v] = ClassGenerator.generate(cls[c]); + } + } + } + + @Benchmark + public Object test() { + return new Object(); + } + +} diff -r 0cb1442be9d6 -r f5ac05188aa1 src/main/java/org/openjdk/gcbench/roots/Code.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/org/openjdk/gcbench/roots/Code.java Wed Nov 22 15:52:08 2017 +0100 @@ -0,0 +1,29 @@ +package org.openjdk.gcbench.roots; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Fork(1) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Threads(Threads.MAX) +@State(Scope.Thread) +public class Code { + + static final MyIntHolder constant = new MyIntHolder(); + + @Benchmark + public int test() { + return constant.x; + } + + static class MyIntHolder { + int x; + } +} diff -r 0cb1442be9d6 -r f5ac05188aa1 src/main/java/org/openjdk/gcbench/roots/NewSync.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/org/openjdk/gcbench/roots/NewSync.java Wed Nov 22 15:52:08 2017 +0100 @@ -0,0 +1,51 @@ +package org.openjdk.gcbench.roots; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Fork(1) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Threads(Threads.MAX) +@State(Scope.Benchmark) +public class NewSync { + + SyncPair[] pairs; + + @Param({"100000"}) + int size; + + @Setup + public void setup() { + pairs = new SyncPair[size]; + for (int c = 0; c < size; c++) { + pairs[c] = new SyncPair(); + } + } + + @TearDown(Level.Iteration) + public void gc() { + System.gc(); + } + + @Benchmark + public void test() throws InterruptedException { + for (SyncPair pair : pairs) { + pair.move(); + } + } + + static class SyncPair { + int x, y; + public synchronized void move() { + x++; + y--; + } + } + +} diff -r 0cb1442be9d6 -r f5ac05188aa1 src/main/java/org/openjdk/gcbench/roots/NewSyncReentrant.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/org/openjdk/gcbench/roots/NewSyncReentrant.java Wed Nov 22 15:52:08 2017 +0100 @@ -0,0 +1,57 @@ +package org.openjdk.gcbench.roots; + +import org.openjdk.jmh.annotations.*; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; + +@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Fork(1) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Threads(Threads.MAX) +@State(Scope.Benchmark) +public class NewSyncReentrant { + + SyncPair[] pairs; + + @Param({"100000"}) + int size; + + @Setup + public void setup() { + pairs = new SyncPair[size]; + for (int c = 0; c < size; c++) { + pairs[c] = new SyncPair(); + } + } + + @TearDown(Level.Iteration) + public void gc() { + System.gc(); + } + + @Benchmark + public void test() throws InterruptedException { + for (SyncPair pair : pairs) { + pair.move(); + } + } + + static class SyncPair { + final ReentrantLock lock = new ReentrantLock(); + int x, y; + + public void move() { + lock.lock(); + try { + x++; + y--; + } finally { + lock.unlock(); + } + } + } + +} diff -r 0cb1442be9d6 -r f5ac05188aa1 src/main/java/org/openjdk/gcbench/roots/ReentrantLocks.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/org/openjdk/gcbench/roots/ReentrantLocks.java Wed Nov 22 15:52:08 2017 +0100 @@ -0,0 +1,45 @@ +package org.openjdk.gcbench.roots; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; + +@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Fork(1) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Threads(Threads.MAX) +@State(Scope.Thread) +public class ReentrantLocks { + + List list; + + @Param({"40000"}) + private int size; + + @Setup + public void setup() { + list = new ArrayList<>(); + for (int c = 0; c < size; c++) { + list.add(new ReentrantLock()); + } + } + + @Benchmark + public void test(Blackhole bh) throws InterruptedException { + for (ReentrantLock lock : list) { + lock.lock(); + } + bh.consume(new byte[100000]); + for (ReentrantLock lock : list) { + lock.newCondition().await(1, TimeUnit.NANOSECONDS); + lock.unlock(); + } + } + +}