changeset 1352:76b65108ea90

7901799: Control objects should be notified consistently
author shade
date Tue, 20 Sep 2016 11:36:29 +0200
parents 8c20adb08b2d
children eaf181b4eac2
files jmh-core-it/src/test/java/org/openjdk/jmh/it/control/ControlStartStopTest.java jmh-core-it/src/test/java/org/openjdk/jmh/it/control/ControlStopTest.java jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java jmh-core/src/main/java/org/openjdk/jmh/runner/BenchmarkHandler.java jmh-core/src/main/java/org/openjdk/jmh/runner/InfraControl.java
diffstat 5 files changed, 170 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/control/ControlStartStopTest.java	Tue Sep 20 11:36:29 2016 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016, Red Hat Inc. 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.it.control;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.infra.Control;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+
+@Warmup(iterations = 5, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 5, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+public class ControlStartStopTest {
+
+    @Benchmark
+    public void ping(Control cnt) {
+        boolean stop = cnt.stopMeasurement;
+        boolean start = cnt.startMeasurement;
+
+        // stop should always be preceded by start
+        Assert.assertFalse(stop && !start);
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (Mode m : Mode.values()) {
+            if (m == Mode.All) continue;
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .mode(m)
+                    .build();
+            new Runner(opt).runSingle();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/control/ControlStopTest.java	Tue Sep 20 11:36:29 2016 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016, Red Hat Inc. 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.it.control;
+
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.infra.Control;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+
+@Warmup(iterations = 5, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 5, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+public class ControlStopTest {
+
+    @Benchmark
+    @Group("pingpong")
+    public void ping(Control cnt) {
+        while (!cnt.stopMeasurement) {
+            // this body is intentionally left blank
+        }
+    }
+
+    @Benchmark
+    @Group("pingpong")
+    public void pong(Control cnt) {
+        while (!cnt.stopMeasurement) {
+            // this body is intentionally left blank
+        }
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (Mode m : Mode.values()) {
+            if (m == Mode.All) continue;
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .mode(m)
+                    .build();
+            new Runner(opt).runSingle();
+        }
+    }
+
+}
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java	Thu Sep 15 17:44:47 2016 +0200
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java	Tue Sep 20 11:36:29 2016 +0200
@@ -836,7 +836,7 @@
         writer.println(ident(2) + "this.benchmarkParams = control.benchmarkParams;");
         writer.println(ident(2) + "this.iterationParams = control.iterationParams;");
         writer.println(ident(2) + "this.threadParams    = threadParams;");
-        writer.println(ident(2) + "this.notifyControl   = new Control();");
+        writer.println(ident(2) + "this.notifyControl   = control.notifyControl;");
         writer.println(ident(2) + "this.blackhole       = new Blackhole(\"Today's password is swordfish. I understand instantiating Blackholes directly is dangerous.\");");
     }
 
@@ -1015,6 +1015,9 @@
 
             iterationProlog(writer, 3, method, states);
 
+            // control objects get a special treatment
+            writer.println(ident(3) + "notifyControl.startMeasurement = true;");
+
             // measurement loop call
             writer.println(ident(3) + "RawResults res = new RawResults();");
             writer.println(ident(3) + "int batchSize = iterationParams.getBatchSize();");
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/BenchmarkHandler.java	Thu Sep 15 17:44:47 2016 +0200
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/BenchmarkHandler.java	Tue Sep 20 11:36:29 2016 +0200
@@ -25,6 +25,7 @@
 package org.openjdk.jmh.runner;
 
 import org.openjdk.jmh.infra.BenchmarkParams;
+import org.openjdk.jmh.infra.Control;
 import org.openjdk.jmh.infra.IterationParams;
 import org.openjdk.jmh.infra.ThreadParams;
 import org.openjdk.jmh.profile.InternalProfiler;
@@ -311,7 +312,9 @@
         // result object to accumulate the results in
         List<Result> iterationResults = new ArrayList<Result>();
 
-        InfraControl control = new InfraControl(benchmarkParams, params, preSetupBarrier, preTearDownBarrier, last);
+        InfraControl control = new InfraControl(benchmarkParams, params,
+                preSetupBarrier, preTearDownBarrier, last,
+                new Control());
 
         // preparing the worker runnables
         BenchmarkTask[] runners = new BenchmarkTask[numThreads];
@@ -358,7 +361,7 @@
         }
 
         // now we communicate all worker threads should stop
-        control.isDone = true;
+        control.announceDone();
 
         // wait for all workers to transit to teardown
         control.awaitWarmdownReady();
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/InfraControl.java	Thu Sep 15 17:44:47 2016 +0200
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/InfraControl.java	Tue Sep 20 11:36:29 2016 +0200
@@ -25,6 +25,7 @@
 package org.openjdk.jmh.runner;
 
 import org.openjdk.jmh.infra.BenchmarkParams;
+import org.openjdk.jmh.infra.Control;
 import org.openjdk.jmh.infra.IterationParams;
 import org.openjdk.jmh.util.Utils;
 
@@ -54,8 +55,10 @@
         Utils.check(InfraControl.class, "shouldSynchIterations", "threads");
     }
 
-    public InfraControl(BenchmarkParams benchmarkParams, IterationParams iterationParams, CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration) {
-        super(benchmarkParams, iterationParams, preSetup, preTearDown, lastIteration);
+    public InfraControl(BenchmarkParams benchmarkParams, IterationParams iterationParams,
+                        CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration,
+                        Control notifyControl) {
+        super(benchmarkParams, iterationParams, preSetup, preTearDown, lastIteration, notifyControl);
     }
 
     /**
@@ -98,6 +101,12 @@
     public boolean isLastIteration() {
         return lastIteration;
     }
+
+    public void announceDone() {
+        isDone = true;
+        notifyControl.stopMeasurement = true;
+    }
+
 }
 
 abstract class InfraControlL0 {
@@ -141,11 +150,14 @@
 
     public final BenchmarkParams benchmarkParams;
     public final IterationParams iterationParams;
+    public final Control notifyControl;
 
     private final boolean shouldSynchIterations;
     private final int threads;
 
-    public InfraControlL2(BenchmarkParams benchmarkParams, IterationParams iterationParams, CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration) {
+    public InfraControlL2(BenchmarkParams benchmarkParams, IterationParams iterationParams,
+                          CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration,
+                          Control notifyControl) {
         warmupVisited = new AtomicInteger();
         warmdownVisited = new AtomicInteger();
 
@@ -158,6 +170,8 @@
         warmupShouldWait = shouldSynchIterations;
         warmdownShouldWait = shouldSynchIterations;
 
+        this.notifyControl = notifyControl;
+
         this.preSetup = preSetup;
         this.preTearDown = preTearDown;
         this.lastIteration = lastIteration;
@@ -240,16 +254,20 @@
     private boolean q161, q162, q163, q164, q165, q166, q167, q168;
     private boolean q171, q172, q173, q174, q175, q176, q177, q178;
 
-    public InfraControlL3(BenchmarkParams benchmarkParams, IterationParams iterationParams, CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration) {
-        super(benchmarkParams, iterationParams, preSetup, preTearDown, lastIteration);
+    public InfraControlL3(BenchmarkParams benchmarkParams, IterationParams iterationParams,
+                          CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration,
+                          Control notifyControl) {
+        super(benchmarkParams, iterationParams, preSetup, preTearDown, lastIteration, notifyControl);
     }
 }
 
 abstract class InfraControlL4 extends InfraControlL3 {
     private int markerEnd;
 
-    public InfraControlL4(BenchmarkParams benchmarkParams, IterationParams iterationParams, CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration) {
-        super(benchmarkParams, iterationParams, preSetup, preTearDown, lastIteration);
+    public InfraControlL4(BenchmarkParams benchmarkParams, IterationParams iterationParams,
+                          CountDownLatch preSetup, CountDownLatch preTearDown, boolean lastIteration,
+                          Control notifyControl) {
+        super(benchmarkParams, iterationParams, preSetup, preTearDown, lastIteration, notifyControl);
     }
 }