RFR: Merge LoopMicroBenchmarkHandler & ShotMicroBenchmarkHandler back into the single class.

Sergey Kuksenko sergey.kuksenko at oracle.com
Tue Jun 11 05:47:05 PDT 2013


Hi,

Implementations of classes LoopMicroBenchmarkHandler and 
ShotMicroBenchmarkHandler are very similar. The only minor difference 
exists between Loop* and Shot* logic. Merging all logic back into the 
single class will be much less error prone and much more convenient for 
further development.

-----------patch starts here-----------------------------------------
diff -r 81994ce1bd24 
jmh-core/src/main/java/org/openjdk/jmh/runner/LoopMicroBenchmarkHandler.java
--- 
a/jmh-core/src/main/java/org/openjdk/jmh/runner/LoopMicroBenchmarkHandler.java 
Tue Jun 11 12:30:05 2013 +0400
+++ 
b/jmh-core/src/main/java/org/openjdk/jmh/runner/LoopMicroBenchmarkHandler.java 
Tue Jun 11 16:13:06 2013 +0400
@@ -25,6 +25,7 @@
  package org.openjdk.jmh.runner;


+import org.openjdk.jmh.annotations.Mode;
  import org.openjdk.jmh.logic.Loop;
  import org.openjdk.jmh.logic.results.IterationData;
  import org.openjdk.jmh.logic.results.Result;
@@ -36,14 +37,11 @@
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
  import java.util.List;
  import java.util.concurrent.Callable;
  import java.util.concurrent.CountDownLatch;
  import java.util.concurrent.ExecutionException;
  import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
  import java.util.concurrent.TimeoutException;

  /**
@@ -78,7 +76,7 @@
      LoopMicroBenchmarkHandler(OutputFormat format, BenchmarkRecord 
microbenchmark, Class<?> clazz, Method method, BaseOptions options, 
MicroBenchmarkParameters executionParams) {
          super(format, microbenchmark, clazz, options, executionParams);
          this.method = method;
-        this.shouldSynchIterations = 
executionParams.shouldSynchIterations();
+        this.shouldSynchIterations = (microbenchmark.getMode() != 
Mode.SingleShotTime) && executionParams.shouldSynchIterations();
          this.shouldFailOnError = options.shouldFailOnError();
          this.shouldTraceBenchmarkStartStop = 
options.shouldTraceBenchmarkStartStop();
      }
@@ -201,16 +199,18 @@
                  loop.preSetupForce();
                  loop.preTearDownForce();

-                try {
-                    loop.announceWarmupReady();
-                } catch (Exception e1) {
-                    // more threads than expected
-                }
+                if (shouldSynchIterations) {
+                    try {
+                        loop.announceWarmupReady();
+                    } catch (Exception e1) {
+                        // more threads than expected
+                    }

-                try {
-                    loop.announceWarmdownReady();
-                } catch (Exception e1) {
-                    // more threads than expected
+                    try {
+                        loop.announceWarmdownReady();
+                    } catch (Exception e1) {
+                        // more threads than expected
+                    }
                  }

                  throw new Exception(e); // wrapping Throwable
diff -r 81994ce1bd24 
jmh-core/src/main/java/org/openjdk/jmh/runner/MicroBenchmarkHandlers.java
--- 
a/jmh-core/src/main/java/org/openjdk/jmh/runner/MicroBenchmarkHandlers.java 
Tue Jun 11 12:30:05 2013 +0400
+++ 
b/jmh-core/src/main/java/org/openjdk/jmh/runner/MicroBenchmarkHandlers.java 
Tue Jun 11 16:13:06 2013 +0400
@@ -70,11 +70,7 @@
      }

      public static MicroBenchmarkHandler getInstance(OutputFormat 
outputHandler, BenchmarkRecord microbenchmark, Class<?> clazz, Method 
method, MicroBenchmarkParameters executionParams, BaseOptions options) {
-        if(microbenchmark.getMode() == Mode.SingleShotTime) {
-            return new ShotMicroBenchmarkHandler(outputHandler, 
microbenchmark, clazz, method, options, executionParams);
-        } else {
-            return new LoopMicroBenchmarkHandler(outputHandler, 
microbenchmark, clazz, method, options, executionParams);
-        }
+        return new LoopMicroBenchmarkHandler(outputHandler, 
microbenchmark, clazz, method, options, executionParams);
      }

      /**
diff -r 81994ce1bd24 
jmh-core/src/main/java/org/openjdk/jmh/runner/ShotMicroBenchmarkHandler.java
--- 
a/jmh-core/src/main/java/org/openjdk/jmh/runner/ShotMicroBenchmarkHandler.java 
Tue Jun 11 12:30:05 2013 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-/**
- * 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.runner;
-
-import org.openjdk.jmh.logic.Loop;
-import org.openjdk.jmh.logic.results.IterationData;
-import org.openjdk.jmh.logic.results.Result;
-import org.openjdk.jmh.output.format.OutputFormat;
-import org.openjdk.jmh.runner.options.BaseOptions;
-import org.openjdk.jmh.runner.parameters.MicroBenchmarkParameters;
-import org.openjdk.jmh.runner.parameters.TimeValue;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Handler for a single shot micro benchmark.
- * Handles name and execution information (# iterations, et c). 
Executes the
- * benchmark according to above parameters.
- *
- * @author sergey.kuksenko at oracle.com
- */
-public class ShotMicroBenchmarkHandler extends BaseMicroBenchmarkHandler {
-
-    private final Method method;
-
-    /* output options */
-    private final boolean shouldFailOnError;
-    private final boolean shouldTraceBenchmarkStartStop;
-
-    /**
-     * Constructor
-     *
-     * @param microbenchmark  Name of micro benchmark
-     * @param clazz
-     * @param method
-     * @param options      Options from the command line
-     * @param executionParams
-     */
-    ShotMicroBenchmarkHandler(OutputFormat format, BenchmarkRecord 
microbenchmark, Class<?> clazz, Method method, BaseOptions options, 
MicroBenchmarkParameters executionParams) {
-        super(format, microbenchmark, clazz, options, executionParams);
-        this.method = method;
-        this.shouldFailOnError = options.shouldFailOnError();
-        this.shouldTraceBenchmarkStartStop = 
options.shouldTraceBenchmarkStartStop();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public IterationData runIteration(int numThreads, TimeValue 
runtime, boolean last) {
-        // bring up the barrier
-        CountDownLatch preSetupBarrier = new CountDownLatch(numThreads);
-        CountDownLatch preTearDownBarrier = new CountDownLatch(numThreads);
-
-        IterationData iterationResults = new 
IterationData(microbenchmark, numThreads, runtime);
-
-        // create tasks
-        BenchmarkTask[] runners = new BenchmarkTask[numThreads];
-        for (int i = 0; i < runners.length; i++) {
-            runners[i] = new BenchmarkTask(threadLocal, new 
Loop(numThreads, TimeValue.NONE, preSetupBarrier, preTearDownBarrier, 
last, false, timeUnit));
-        }
-
-        // submit tasks to threadpool
-        List<Future<Result>> resultList = new 
ArrayList<Future<Result>>(numThreads);
-        for (BenchmarkTask runner : runners) {
-            resultList.add(executor.submit(runner));
-        }
-
-        // wait for all threads to start executing
-        try {
-            preSetupBarrier.await();
-        } catch (InterruptedException ex) {
-            log(ex);
-        }
-
-        startProfilers();
-
-        // wait for all threads to stop executing
-        try {
-            preTearDownBarrier.await();
-        } catch (InterruptedException ex) {
-            log(ex);
-        }
-
-        stopProfilers(iterationResults);
-
-        // wait for the result, continuously polling the worker threads.
-        //
-        int expected = numThreads;
-        while (expected > 0) {
-            for (Future<Result> fr : resultList) {
-                try {
-                    fr.get(runtime.getTime() * 2, runtime.getTimeUnit());
-                    expected--;
-                } catch (InterruptedException ex) {
-                    log(ex);
-                    iterationResults.clearResults();
-                    return iterationResults;
-                } catch (ExecutionException ex) {
-                    Throwable cause = ex.getCause().getCause(); // unwrap
-                    log(cause);
-                    iterationResults.clearResults();
-                    if (shouldFailOnError) {
-                        throw new 
IllegalStateException(cause.getMessage(), cause);
-                    }
-                    return iterationResults;
-                } catch (TimeoutException e) {
-                    // do nothing, respin
-                }
-            }
-        }
-
-        // get the results
-        for (Future<Result> fr : resultList) {
-            try {
-                iterationResults.addResult(fr.get());
-            } catch (InterruptedException ex) {
-                throw new IllegalStateException("Impossible to be here");
-            } catch (ExecutionException ex) {
-                throw new IllegalStateException("Impossible to be here");
-            }
-        }
-
-        return iterationResults;
-    }
-
-    /**
-     * Task to submit to the ExecutorService. Will execute one 
iteration and return the Result.
-     *
-     * @author anders.astrand at oracle.com
-     */
-    class BenchmarkTask implements Callable<Result> {
-
-        /**
-         * Microbenchmark instance to execute on
-         */
-        private final ThreadLocal<InstanceProvider> invocationHandler;
-        /**
-         * Barrier, to synchronize threads with
-         */
-        private Loop loop;
-
-        /**
-         * Constructor
-         *
-         * @param invocationHandler    instance to execute on
-         */
-        BenchmarkTask(ThreadLocal<InstanceProvider> invocationHandler, 
Loop loop) {
-            this.invocationHandler = invocationHandler;
-            this.loop = loop;
-        }
-
-        @Override
-        public Result call() throws Exception {
-            try {
-                return 
invokeBenchmark(invocationHandler.get().getInstance());
-            } catch (Throwable e) {
-                // about to fail the iteration;
-                // compensate for missed sync-iteration latches, we 
don't care about that anymore
-                loop.preSetupForce();
-                loop.preTearDownForce();
-                throw new Exception(e); // wrapping Throwable
-            }
-        }
-
-        /**
-         * Helper method for running the benchmark in a given instance.
-         *
-         * @return the Result of the execution
-         * @throws Exception if something went wrong
-         */
-        private Result invokeBenchmark(Object instance) throws Throwable {
-            Result result;
-            if (shouldTraceBenchmarkStartStop) {
-                format.traceStartIteration();
-            }
-
-            if (method != null) {
-                try {
-                    result = (Result) method.invoke(instance, loop);
-                } catch (IllegalAccessException e) {
-                    throw new RuntimeException("Can't invoke " + 
method.getDeclaringClass().getName() + "." + method.getName(), e);
-                } catch (InvocationTargetException e) {
-                    throw e.getCause(); // unwrap
-                }
-            } else {
-                throw new IllegalStateException("Unable to find method 
to run");
-            }
-
-            if (shouldTraceBenchmarkStartStop) {
-                format.traceEndIteration();
-            }
-
-            return result;
-        }
-
-    }
-
-}
-
-


More information about the jmh-dev mailing list