changeset 91:3ba7f2895341

Regression: Revive synchronize iterations, threads should share the global state handling the sync iteration state.
author shade
date Tue, 11 Jun 2013 18:08:27 +0400
parents 9cb8d98f87c1
children 12b90923045c
files jmh-core/src/main/java/org/openjdk/jmh/logic/Global.java jmh-core/src/main/java/org/openjdk/jmh/logic/Loop.java jmh-core/src/main/java/org/openjdk/jmh/processor/internal/GenerateMicroBenchmarkProcessor.java jmh-core/src/main/java/org/openjdk/jmh/runner/LoopMicroBenchmarkHandler.java
diffstat 4 files changed, 144 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/logic/Global.java	Tue Jun 11 18:08:27 2013 +0400
@@ -0,0 +1,112 @@
+/**
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.logic;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class Global extends GlobalL4 {
+
+    public Global(int threads, boolean syncIterations) {
+        super(threads, syncIterations);
+    }
+
+}
+
+class GlobalL1 {
+    public int p01, p02, p03, p04, p05, p06, p07, p08;
+    public int p11, p12, p13, p14, p15, p16, p17, p18;
+    public int p21, p22, p23, p24, p25, p26, p27, p28;
+    public int p31, p32, p33, p34, p35, p36, p37, p38;
+}
+
+/**
+ * @see BlackHole for rationale
+ */
+class GlobalL2 extends GlobalL1 {
+    public final int threads;
+    public final boolean syncIterations;
+
+    public final AtomicInteger warmupVisited, warmdownVisited;
+    public volatile boolean warmupShouldWait, warmdownShouldWait;
+
+    public GlobalL2(int threads, boolean syncIterations) {
+        this.threads = threads;
+        this.syncIterations = syncIterations;
+        this.warmupVisited = new AtomicInteger();
+        this.warmdownVisited = new AtomicInteger();
+
+        if (!syncIterations) {
+            warmupShouldWait = false;
+            warmdownShouldWait = false;
+        } else {
+            warmupShouldWait = true;
+            warmdownShouldWait = true;
+        }
+    }
+
+    public void announceWarmupReady() {
+        if (!syncIterations) return;
+        int v = warmupVisited.incrementAndGet();
+        if (v == threads) {
+            warmupShouldWait = false;
+        }
+
+        if (v > threads) {
+            throw new IllegalStateException("More threads than expected");
+        }
+    }
+
+    public void announceWarmdownReady() {
+        if (!syncIterations) return;
+        int v = warmdownVisited.incrementAndGet();
+        if (v == threads) {
+            warmdownShouldWait = false;
+        }
+
+        if (v > threads) {
+            throw new IllegalStateException("More threads than expected");
+        }
+    }
+}
+
+class GlobalL3 extends GlobalL2 {
+    public int e01, e02, e03, e04, e05, e06, e07, e08;
+    public int e11, e12, e13, e14, e15, e16, e17, e18;
+    public int e21, e22, e23, e24, e25, e26, e27, e28;
+    public int e31, e32, e33, e34, e35, e36, e37, e38;
+
+    public GlobalL3(int threads, boolean syncIterations) {
+        super(threads, syncIterations);
+    }
+}
+
+class GlobalL4 extends GlobalL3 {
+    public int marker;
+
+    public GlobalL4(int threads, boolean syncIterations) {
+        super(threads, syncIterations);
+    }
+
+}
--- a/jmh-core/src/main/java/org/openjdk/jmh/logic/Loop.java	Tue Jun 11 17:34:05 2013 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/logic/Loop.java	Tue Jun 11 18:08:27 2013 +0400
@@ -31,7 +31,6 @@
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * The Loop logic class. Controls if we should iterate another lap in the benchmark loop via calls to done();
@@ -67,11 +66,11 @@
      * @param loopTime How long we should loop
      */
     public Loop(TimeValue loopTime) {
-        this(1, loopTime, null, null, false, false, null);
+        this(null, loopTime, null, null, false, null);
     }
 
-    public Loop(int threads, TimeValue loopTime, CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration, boolean syncIterations, TimeUnit timeUnit) {
-        super(threads, loopTime, preSetup, preTearDown, lastIteration, syncIterations, timeUnit);
+    public Loop(Global global, TimeValue loopTime, CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration, TimeUnit timeUnit) {
+        super(global, loopTime, preSetup, preTearDown, lastIteration, timeUnit);
     }
 
 
@@ -193,38 +192,6 @@
         return unit.convert(duration, TimeUnit.NANOSECONDS);
     }
 
-    public boolean shouldContinueWarmup() {
-        return warmupShouldWait;
-    }
-
-    public boolean shouldContinueWarmdown() {
-        return warmdownShouldWait;
-    }
-
-    public void announceWarmupReady() {
-        if (!syncIterations) return;
-        int v = warmupVisited.incrementAndGet();
-        if (v == threads) {
-            warmupShouldWait = false;
-        }
-
-        if (v > threads) {
-            throw new IllegalStateException("More threads than expected");
-        }
-    }
-
-    public void announceWarmdownReady() {
-        if (!syncIterations) return;
-        int v = warmdownVisited.incrementAndGet();
-        if (v == threads) {
-            warmdownShouldWait = false;
-        }
-
-        if (v > threads) {
-            throw new IllegalStateException("More threads than expected");
-        }
-    }
-
     public void preSetup() {
         try {
             preSetup.countDown();
@@ -283,34 +250,21 @@
     /** Total pause time */
     public long totalPause;
 
-    public final int threads;
     public final CountDownLatch preSetup;
     public final CountDownLatch preTearDown;
     public final boolean lastIteration;
-    public final boolean syncIterations;
 
-    public final AtomicInteger warmupVisited, warmdownVisited;
-    public volatile boolean warmupShouldWait, warmdownShouldWait;
+    public final Global global;
 
     public final TimeUnit timeUnit;
 
-    public LoopL2(int threads, TimeValue loopTime, CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration, boolean syncIterations, TimeUnit timeUnit) {
-        this.threads = threads;
+    public LoopL2(Global global, TimeValue loopTime, CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration, TimeUnit timeUnit) {
         this.preSetup = preSetup;
         this.preTearDown = preTearDown;
         this.duration = loopTime.convertTo(TimeUnit.NANOSECONDS);
         this.lastIteration = lastIteration;
-
-        this.warmupVisited = new AtomicInteger();
-        this.warmdownVisited = new AtomicInteger();
-
-        if (!syncIterations) {
-            warmupShouldWait = false;
-            warmdownShouldWait = false;
-        }
-
-        this.syncIterations = syncIterations;
         this.timeUnit = timeUnit;
+        this.global = global;
     }
 }
 
@@ -320,16 +274,16 @@
     public int e21, e22, e23, e24, e25, e26, e27, e28;
     public int e31, e32, e33, e34, e35, e36, e37, e38;
 
-    public LoopL3(int threads, TimeValue loopTime, CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration, boolean syncIterations, TimeUnit timeUnit) {
-        super(threads, loopTime, preSetup, preTearDown, lastIteration, syncIterations, timeUnit);
+    public LoopL3(Global global, TimeValue loopTime, CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration, TimeUnit timeUnit) {
+        super(global, loopTime, preSetup, preTearDown, lastIteration, timeUnit);
     }
 }
 
 class LoopL4 extends LoopL3 {
     public int marker;
 
-    public LoopL4(int threads, TimeValue loopTime, CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration, boolean syncIterations, TimeUnit timeUnit) {
-        super(threads, loopTime, preSetup, preTearDown, lastIteration, syncIterations, timeUnit);
+    public LoopL4(Global global, TimeValue loopTime, CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration, TimeUnit timeUnit) {
+        super(global, loopTime, preSetup, preTearDown, lastIteration, timeUnit);
     }
 }
 
--- a/jmh-core/src/main/java/org/openjdk/jmh/processor/internal/GenerateMicroBenchmarkProcessor.java	Tue Jun 11 17:34:05 2013 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/processor/internal/GenerateMicroBenchmarkProcessor.java	Tue Jun 11 18:08:27 2013 +0400
@@ -26,6 +26,7 @@
 
 import org.openjdk.jmh.annotations.*;
 import org.openjdk.jmh.logic.BlackHole;
+import org.openjdk.jmh.logic.Global;
 import org.openjdk.jmh.logic.Loop;
 import org.openjdk.jmh.logic.results.AverageTimePerOp;
 import org.openjdk.jmh.logic.results.OpsPerTimeUnit;
@@ -431,6 +432,7 @@
         writer.println("import " + Generated.class.getName() + ';');
         writer.println();
         writer.println("import " + Loop.class.getName() + ';');
+        writer.println("import " + Global.class.getName() + ';');
         writer.println("import " + BlackHole.class.getName() + ';');
         writer.println("import " + Result.class.getName() + ';');
         writer.println("import " + OpsPerTimeUnit.class.getName() + ';');
@@ -728,10 +730,10 @@
             invocationEpilog(writer, 3, method, states, false);
 
             // synchronize iterations prolog: announce ready
-            writer.println(ident(3) + "loop.announceWarmupReady();");
+            writer.println(ident(3) + "global.announceWarmupReady();");
 
             // synchronize iterations prolog: catchup loop
-            writer.println(ident(3) + "while (loop.warmupShouldWait) {");
+            writer.println(ident(3) + "while (global.warmupShouldWait) {");
 
             invocationProlog(writer, 4, method, states, false);
             writer.println(ident(4) + emitCall(method, states) + ';');
@@ -755,10 +757,10 @@
             }
 
             // synchronize iterations epilog: announce ready
-            writer.println(ident(3) + "loop.announceWarmdownReady();");
+            writer.println(ident(3) + "global.announceWarmdownReady();");
 
             // synchronize iterations epilog: catchup loop
-            writer.println(ident(3) + "while (loop.warmdownShouldWait) {");
+            writer.println(ident(3) + "while (global.warmdownShouldWait) {");
 
             invocationProlog(writer, 4, method, states, false);
             writer.println(ident(4) + emitCall(method, states) + ';');
@@ -822,10 +824,10 @@
             invocationEpilog(writer, 3, method, states, false);
 
             // synchronize iterations prolog: announce ready
-            writer.println(ident(3) + "loop.announceWarmupReady();");
+            writer.println(ident(3) + "global.announceWarmupReady();");
 
             // synchronize iterations prolog: catchup loop
-            writer.println(ident(3) + "while (loop.warmupShouldWait) {");
+            writer.println(ident(3) + "while (global.warmupShouldWait) {");
 
             invocationProlog(writer, 4, method, states, false);
             writer.println(ident(4) + emitCall(method, states) + ';');
@@ -849,10 +851,10 @@
             }
 
             // synchronize iterations epilog: announce ready
-            writer.println(ident(3) + "loop.announceWarmdownReady();");
+            writer.println(ident(3) + "global.announceWarmdownReady();");
 
             // synchronize iterations epilog: catchup loop
-            writer.println(ident(3) + "while (loop.warmdownShouldWait) {");
+            writer.println(ident(3) + "while (global.warmdownShouldWait) {");
 
             invocationProlog(writer, 4, method, states, false);
             writer.println(ident(4) + emitCall(method, states) + ';');
@@ -901,6 +903,8 @@
         writer.println(ident(2) + "int groupId = threadId / groupThreadCount;");
         writer.println(ident(2) + "int siblingId = threadId % groupThreadCount;");
         writer.println();
+        writer.println(ident(2) + "Global global = loop.global;");
+        writer.println();
     }
 
     private String prefix(String argList) {
@@ -935,10 +939,10 @@
             invocationEpilog(writer, 3, method, states, false);
 
             // synchronize iterations prolog: announce ready
-            writer.println(ident(3) + "loop.announceWarmupReady();");
+            writer.println(ident(3) + "global.announceWarmupReady();");
 
             // synchronize iterations prolog: catchup loop
-            writer.println(ident(3) + "while (loop.warmupShouldWait) {");
+            writer.println(ident(3) + "while (global.warmupShouldWait) {");
 
             invocationProlog(writer, 4, method, states, false);
             writer.println(ident(4) + emitCall(method, states) + ';');
@@ -961,10 +965,10 @@
             }
 
             // synchronize iterations epilog: announce ready
-            writer.println(ident(3) + "loop.announceWarmdownReady();");
+            writer.println(ident(3) + "global.announceWarmdownReady();");
 
             // synchronize iterations epilog: catchup loop
-            writer.println(ident(3) + "while (loop.warmdownShouldWait) {");
+            writer.println(ident(3) + "while (global.warmdownShouldWait) {");
 
             invocationProlog(writer, 4, method, states, false);
             writer.println(ident(4) + emitCall(method, states) + ';');
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/LoopMicroBenchmarkHandler.java	Tue Jun 11 17:34:05 2013 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/LoopMicroBenchmarkHandler.java	Tue Jun 11 18:08:27 2013 +0400
@@ -26,6 +26,7 @@
 
 
 import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.logic.Global;
 import org.openjdk.jmh.logic.Loop;
 import org.openjdk.jmh.logic.results.IterationData;
 import org.openjdk.jmh.logic.results.Result;
@@ -88,11 +89,13 @@
         CountDownLatch preSetupBarrier = new CountDownLatch(numThreads);
         CountDownLatch preTearDownBarrier = new CountDownLatch(numThreads);
 
+        Global global = new Global(numThreads, shouldSynchIterations);
+
         IterationData iterationResults = new IterationData(microbenchmark, numThreads, runtime);
 
         BenchmarkTask[] runners = new BenchmarkTask[numThreads];
         for (int i = 0; i < runners.length; i++) {
-            runners[i] = new BenchmarkTask(threadLocal, new Loop(numThreads, runtime, preSetupBarrier, preTearDownBarrier, last, shouldSynchIterations, timeUnit));
+            runners[i] = new BenchmarkTask(threadLocal, new Loop(global, runtime, preSetupBarrier, preTearDownBarrier, last, timeUnit));
         }
 
         // submit tasks to threadpool
@@ -199,13 +202,13 @@
 
                 if (shouldSynchIterations) {
                     try {
-                        loop.announceWarmupReady();
+                        loop.global.announceWarmupReady();
                     } catch (Exception e1) {
                         // more threads than expected
                     }
 
                     try {
-                        loop.announceWarmdownReady();
+                        loop.global.announceWarmdownReady();
                     } catch (Exception e1) {
                         // more threads than expected
                     }