changeset 1325:49e2fb0c9f3b

7901707: Ability to use different JVM options for different forks
author shade
date Wed, 13 Jul 2016 01:00:45 +0300
parents 70dfb4a93cf5
children cffb77974716
files jmh-core-it/src/test/java/org/openjdk/jmh/it/profilers/ChangeJVMOptsExternalProfiler.java jmh-core-it/src/test/java/org/openjdk/jmh/it/profilers/ChangeJVMOptsTest.java jmh-core-it/src/test/resources/META-INF/services/org.openjdk.jmh.profile.Profiler jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java jmh-core/src/main/java/org/openjdk/jmh/util/FileUtils.java jmh-core/src/test/java/org/openjdk/jmh/runner/RunnerTest.java
diffstat 6 files changed, 221 insertions(+), 11 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/profilers/ChangeJVMOptsExternalProfiler.java	Wed Jul 13 01:00:45 2016 +0300
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2014, 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.it.profilers;
+
+import org.openjdk.jmh.infra.BenchmarkParams;
+import org.openjdk.jmh.profile.ExternalProfiler;
+import org.openjdk.jmh.results.BenchmarkResult;
+import org.openjdk.jmh.results.Result;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+
+public class ChangeJVMOptsExternalProfiler implements ExternalProfiler {
+
+    @Override
+    public Collection<String> addJVMInvokeOptions(BenchmarkParams params) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Collection<String> addJVMOptions(BenchmarkParams params) {
+        return Collections.singletonList("-Dkey=" + Math.random());
+    }
+
+    @Override
+    public void beforeTrial(BenchmarkParams benchmarkParams) {
+        // intentionally left blank
+    }
+
+    @Override
+    public Collection<? extends Result> afterTrial(BenchmarkResult br, long pid, File stdOut, File stdErr) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public boolean allowPrintOut() {
+        return true;
+    }
+
+    @Override
+    public boolean allowPrintErr() {
+        return true;
+    }
+
+    @Override
+    public String getDescription() {
+        return "Changing JVM Opts Integration Test External Profiler";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/profilers/ChangeJVMOptsTest.java	Wed Jul 13 01:00:45 2016 +0300
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2014, 2014, 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.it.profilers;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.*;
+import org.openjdk.jmh.util.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+@State(Scope.Benchmark)
+public class ChangeJVMOptsTest {
+
+    public static final File TMP_FILE = new File(System.getProperty("java.io.tmpdir") + File.separator + "ChangingJVMOpts-list");
+
+    @Setup(Level.Trial)
+    public void setup() {
+        try {
+            FileUtils.appendLines(TMP_FILE,
+                    Collections.singleton(ManagementFactory.getRuntimeMXBean().getInputArguments().toString()));
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Benchmark
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 1, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(value = 5, warmups = 5)
+    public void bench() {
+      // intentionally left blank
+    }
+
+    @Test
+    public void testExternal_API() throws RunnerException, IOException {
+        prepare();
+
+        Options opts = new OptionsBuilder()
+                .include(Fixtures.getTestMask(this.getClass()))
+                .warmupForks(5)
+                .forks(5)
+                .addProfiler(ChangeJVMOptsExternalProfiler.class)
+                .build();
+        new Runner(opts).run();
+
+        check();
+    }
+
+    @Test
+    public void testExternal_CLI() throws RunnerException, CommandLineOptionException, IOException {
+        prepare();
+
+        Options opts = new CommandLineOptions("-prof", ChangeJVMOptsExternalProfiler.class.getCanonicalName(), Fixtures.getTestMask(this.getClass()));
+        new Runner(opts).run();
+
+        check();
+    }
+
+    private void prepare() {
+        TMP_FILE.delete();
+    }
+
+    private void check() throws IOException {
+        Set<String> lines = new HashSet<String>();
+        for (String line : FileUtils.readAllLines(TMP_FILE)) {
+            if (!lines.add(line)) {
+                Assert.fail("Duplicate line: " + line);
+            }
+        }
+    }
+
+}
--- a/jmh-core-it/src/test/resources/META-INF/services/org.openjdk.jmh.profile.Profiler	Tue Jul 12 23:46:52 2016 +0300
+++ b/jmh-core-it/src/test/resources/META-INF/services/org.openjdk.jmh.profile.Profiler	Wed Jul 13 01:00:45 2016 +0300
@@ -1,5 +1,6 @@
 org.openjdk.jmh.it.profilers.ItInternalProfiler
 org.openjdk.jmh.it.profilers.ItExternalProfiler
+org.openjdk.jmh.it.profilers.ChangeJVMOptsExternalProfiler
 org.openjdk.jmh.it.profilers.order.InternalProfiler1
 org.openjdk.jmh.it.profilers.order.InternalProfiler2
 org.openjdk.jmh.it.profilers.order.InternalProfiler3
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java	Tue Jul 12 23:46:52 2016 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java	Wed Jul 13 01:00:45 2016 +0300
@@ -587,11 +587,7 @@
 
             boolean printOut = true;
             boolean printErr = true;
-            List<String> javaInvokeOptions = new ArrayList<String>();
-            List<String> javaOptions = new ArrayList<String>();
             for (ExternalProfiler prof : profilers) {
-                javaInvokeOptions.addAll(prof.addJVMInvokeOptions(params));
-                javaOptions.addAll(prof.addJVMOptions(params));
                 printOut &= prof.allowPrintOut();
                 printErr &= prof.allowPrintErr();
             }
@@ -603,7 +599,6 @@
             printOut = forcePrint || printOut;
             printErr = forcePrint || printErr;
 
-            List<String> forkedString  = getForkedMainCommand(params, javaInvokeOptions, javaOptions, server.getHost(), server.getPort());
             List<String> versionString = getVersionMainCommand(params);
 
             String opts = Utils.join(params.getJvmArgs(), " ");
@@ -621,8 +616,10 @@
             int forkCount = params.getForks();
             int warmupForkCount = params.getWarmupForks();
             if (warmupForkCount > 0) {
-                out.verbosePrintln("Warmup forking " + warmupForkCount + " times using command: " + forkedString);
                 for (int i = 0; i < warmupForkCount; i++) {
+                    List<String> forkedString  = getForkedMainCommand(params, profilers, server.getHost(), server.getPort());
+                    out.verbosePrintln("Warmup forking using command: " + forkedString);
+
                     etaBeforeBenchmark();
                     out.println("# Warmup Fork: " + (i + 1) + " of " + warmupForkCount);
 
@@ -636,8 +633,10 @@
                 }
             }
 
-            out.verbosePrintln("Forking " + forkCount + " times using command: " + forkedString);
             for (int i = 0; i < forkCount; i++) {
+                List<String> forkedString  = getForkedMainCommand(params, profilers, server.getHost(), server.getPort());
+                out.verbosePrintln("Forking using command: " + forkedString);
+
                 etaBeforeBenchmark();
                 out.println("# Fork: " + (i + 1) + " of " + forkCount);
 
@@ -786,7 +785,15 @@
      * @param port host VM port
      * @return
      */
-    List<String> getForkedMainCommand(BenchmarkParams benchmark, List<String> javaInvokeOptions, List<String> javaOptions, String host, int port) {
+    List<String> getForkedMainCommand(BenchmarkParams benchmark, List<ExternalProfiler> profilers, String host, int port) {
+        // Poll profilers for options
+        List<String> javaInvokeOptions = new ArrayList<String>();
+        List<String> javaOptions = new ArrayList<String>();
+        for (ExternalProfiler prof : profilers) {
+            javaInvokeOptions.addAll(prof.addJVMInvokeOptions(benchmark));
+            javaOptions.addAll(prof.addJVMOptions(benchmark));
+        }
+
         List<String> command = new ArrayList<String>();
 
         // prefix java invoke options, if any profiler wants it
--- a/jmh-core/src/main/java/org/openjdk/jmh/util/FileUtils.java	Tue Jul 12 23:46:52 2016 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/util/FileUtils.java	Wed Jul 13 01:00:45 2016 +0300
@@ -134,6 +134,30 @@
         }
     }
 
+    public static void writeLines(File file, Collection<String> lines) throws IOException {
+        PrintWriter pw = null;
+        try {
+            pw = new PrintWriter(file);
+            for (String line : lines) {
+                pw.println(line);
+            }
+            pw.close();
+        } finally {
+            FileUtils.safelyClose(pw);
+        }
+    }
+
+    public static void appendLines(File file, Collection<String> lines) throws IOException {
+        Collection<String> newLines = new ArrayList<String>();
+        try {
+            newLines.addAll(readAllLines(file));
+        } catch (IOException e) {
+            // no file
+        }
+        newLines.addAll(lines);
+        writeLines(file, newLines);
+    }
+
     public static Collection<File> getClasses(File root) {
         Collection<File> result = new ArrayList<File>();
 
--- a/jmh-core/src/test/java/org/openjdk/jmh/runner/RunnerTest.java	Tue Jul 12 23:46:52 2016 +0300
+++ b/jmh-core/src/test/java/org/openjdk/jmh/runner/RunnerTest.java	Wed Jul 13 01:00:45 2016 +0300
@@ -28,6 +28,7 @@
 import org.openjdk.jmh.annotations.Mode;
 import org.openjdk.jmh.infra.BenchmarkParams;
 import org.openjdk.jmh.infra.IterationParams;
+import org.openjdk.jmh.profile.ExternalProfiler;
 import org.openjdk.jmh.runner.options.OptionsBuilder;
 import org.openjdk.jmh.runner.options.TimeValue;
 import org.openjdk.jmh.util.FileUtils;
@@ -65,7 +66,7 @@
                 Mode.Throughput, null, TimeUnit.SECONDS, 1,
                 Utils.getCurrentJvm(), Collections.<String>emptyList(),
                 TimeValue.days(1));
-        List<String> command = blade.getForkedMainCommand(bp, Collections.<String>emptyList(), Collections.<String>emptyList(), DUMMY_HOST, DUMMY_PORT);
+        List<String> command = blade.getForkedMainCommand(bp, Collections.<ExternalProfiler>emptyList(), DUMMY_HOST, DUMMY_PORT);
 
         // expecting 1 compile command file
         List<String> files = CompilerHints.getCompileCommandFiles(command);
@@ -96,7 +97,7 @@
                 Mode.Throughput, null, TimeUnit.SECONDS, 1,
                 Utils.getCurrentJvm(), Arrays.asList(CompilerHints.XX_COMPILE_COMMAND_FILE + tempHints),
                 TimeValue.days(1));
-        List<String> command = blade.getForkedMainCommand(bp, Collections.<String>emptyList(), Collections.<String>emptyList(), DUMMY_HOST, DUMMY_PORT);
+        List<String> command = blade.getForkedMainCommand(bp, Collections.<ExternalProfiler>emptyList(), DUMMY_HOST, DUMMY_PORT);
 
         // expecting 1 compile command file
         List<String> files = CompilerHints.getCompileCommandFiles(command);
@@ -132,7 +133,7 @@
                 Utils.getCurrentJvm(),
                 Arrays.asList(CompilerHints.XX_COMPILE_COMMAND_FILE + tempHints1, CompilerHints.XX_COMPILE_COMMAND_FILE + tempHints2),
                 TimeValue.days(1));
-        List<String> command = blade.getForkedMainCommand(bp, Collections.<String>emptyList(), Collections.<String>emptyList(), DUMMY_HOST, DUMMY_PORT);
+        List<String> command = blade.getForkedMainCommand(bp, Collections.<ExternalProfiler>emptyList(), DUMMY_HOST, DUMMY_PORT);
 
         // expecting 1 compile command file
         List<String> files = CompilerHints.getCompileCommandFiles(command);