changeset 87:f5ac05188aa1

Autogenerate class roots tests
author shade
date Wed, 22 Nov 2017 15:52:08 +0100
parents 0cb1442be9d6
children 583fef4276f5
files pom.xml src/main/java/org/openjdk/gcbench/roots/ClassGenerator.java src/main/java/org/openjdk/gcbench/roots/Classes.java src/main/java/org/openjdk/gcbench/roots/Code.java src/main/java/org/openjdk/gcbench/roots/NewSync.java src/main/java/org/openjdk/gcbench/roots/NewSyncReentrant.java src/main/java/org/openjdk/gcbench/roots/ReentrantLocks.java
diffstat 7 files changed, 306 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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 @@
             <version>${jmh.version}</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.ow2.asm</groupId>
+            <artifactId>asm</artifactId>
+            <version>5.0.3</version>
+        </dependency>
     </dependencies>
 
     <properties>
--- /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, "<init>", "()V", null, null);
+            mv.visitCode();
+            mv.visitVarInsn(ALOAD, 0);
+            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()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<String, byte[]> 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
--- /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();
+    }
+
+}
--- /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;
+    }
+}
--- /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--;
+        }
+    }
+
+}
--- /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();
+            }
+        }
+    }
+
+}
--- /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<ReentrantLock> 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();
+        }
+    }
+
+}