changeset 712:9dafecdc7404

profilers: sample external profiler is working.
author shade
date Thu, 29 May 2014 20:49:08 +0400
parents 538bfe563b19
children e637358d295e
files jmh-core/src/main/java/org/openjdk/jmh/logic/results/BenchResult.java jmh-core/src/main/java/org/openjdk/jmh/logic/results/RunResult.java jmh-core/src/main/java/org/openjdk/jmh/profile/DummyExternalProfiler.java jmh-core/src/main/java/org/openjdk/jmh/profile/ExternalProfiler.java jmh-core/src/main/java/org/openjdk/jmh/profile/ProfilerFactory.java jmh-core/src/main/java/org/openjdk/jmh/runner/BaseMicroBenchmarkHandler.java jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java jmh-core/src/test/java/org/openjdk/jmh/runner/RunnerTest.java
diffstat 8 files changed, 171 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/jmh-core/src/main/java/org/openjdk/jmh/logic/results/BenchResult.java	Thu May 29 15:55:27 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/logic/results/BenchResult.java	Thu May 29 20:49:08 2014 +0400
@@ -44,10 +44,12 @@
     private static final long serialVersionUID = 6467912427356048369L;
 
     private final Collection<IterationResult> iterationResults;
+    private final Collection<Result> benchmarkResults;
     private final BenchmarkRecord benchmark;
     private final BenchmarkParams params;
 
     public BenchResult(Collection<IterationResult> data) {
+        this.benchmarkResults = new ArrayList<Result>();
         this.iterationResults = data;
 
         BenchmarkRecord myRecord = null;
@@ -72,8 +74,9 @@
         this.params = myParams;
     }
 
-    public Collection<IterationResult> getRawIterationResults() {
-        return iterationResults;
+    public void amend(Result r) {
+        // FIXME: Assumes secondary result.
+        benchmarkResults.add(r);
     }
 
     public Result getPrimaryResult() {
@@ -87,7 +90,7 @@
     public Collection<Result> getRawPrimaryResults() {
         Collection<Result> rs = new ArrayList<Result>();
         for (IterationResult k : iterationResults) {
-            rs.add(k.getPrimaryResult());
+            rs.addAll(k.getRawPrimaryResults());
         }
         return rs;
     }
@@ -95,10 +98,16 @@
     public Multimap<String, Result> getRawSecondaryResults() {
         Multimap<String, Result> rs = new HashMultimap<String, Result>();
         for (IterationResult k : iterationResults) {
-            for (Map.Entry<String, Result> r : k.getSecondaryResults().entrySet()) {
-                rs.put(r.getKey(), r.getValue());
+            Multimap<String, Result> secondaries = k.getRawSecondaryResults();
+            for (String label : secondaries.keys()) {
+                for (Result r : secondaries.get(label)) {
+                    rs.put(r.getLabel(), r);
+                }
             }
         }
+        for (Result r : benchmarkResults) {
+            rs.put(r.getLabel(), r);
+        }
         return rs;
     }
 
--- a/jmh-core/src/main/java/org/openjdk/jmh/logic/results/RunResult.java	Thu May 29 15:55:27 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/logic/results/RunResult.java	Thu May 29 20:49:08 2014 +0400
@@ -89,9 +89,7 @@
     public Collection<Result> getRawPrimaryResults() {
         Collection<Result> rs = new ArrayList<Result>();
         for (BenchResult br : benchResults) {
-            for (IterationResult ir : br.getRawIterationResults()) {
-                rs.add(ir.getPrimaryResult());
-            }
+            rs.addAll(br.getRawPrimaryResults());
         }
         return rs;
     }
@@ -99,9 +97,10 @@
     public Multimap<String, Result> getRawSecondaryResults() {
         Multimap<String, Result> rs = new HashMultimap<String, Result>();
         for (BenchResult br : benchResults) {
-            for (IterationResult ir : br.getRawIterationResults()) {
-                for (Map.Entry<String, Result> r : ir.getSecondaryResults().entrySet()) {
-                    rs.put(r.getKey(), r.getValue());
+            Multimap<String, Result> secondaries = br.getRawSecondaryResults();
+            for (String label : secondaries.keys()) {
+                for (Result r : secondaries.get(label)) {
+                    rs.put(r.getLabel(), r);
                 }
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/profile/DummyExternalProfiler.java	Thu May 29 20:49:08 2014 +0400
@@ -0,0 +1,95 @@
+/*
+ * 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.profile;
+
+import org.openjdk.jmh.logic.results.AggregationPolicy;
+import org.openjdk.jmh.logic.results.Aggregator;
+import org.openjdk.jmh.logic.results.Result;
+import org.openjdk.jmh.logic.results.ResultRole;
+
+import java.util.Collection;
+import java.util.Collections;
+
+public class DummyExternalProfiler implements ExternalProfiler {
+    @Override
+    public Collection<String> addJVMInvokeOptions() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Collection<String> addJVMOptions() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public void beforeTrial() {
+        // do nothing
+    }
+
+    @Override
+    public Collection<? extends Result> afterTrial() {
+        return Collections.singleton(new MyResult());
+    }
+
+    @Override
+    public Collection<String> checkSupport() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public String label() {
+        return "dummy";
+    }
+
+    @Override
+    public String getDescription() {
+        return "Dummy External Profiler";
+    }
+
+    static class MyResult extends Result<MyResult> {
+        MyResult() {
+            super(ResultRole.SECONDARY, "dummy", of(42), "dummyunit", AggregationPolicy.AVG);
+        }
+
+        @Override
+        public Aggregator<MyResult> getIterationAggregator() {
+            return new MyResultAggregator();
+        }
+
+        @Override
+        public Aggregator<MyResult> getRunAggregator() {
+            return new MyResultAggregator();
+        }
+    }
+
+    static class MyResultAggregator implements Aggregator<MyResult> {
+
+        @Override
+        public Result aggregate(Collection<MyResult> results) {
+            return new MyResult();
+        }
+    }
+
+}
--- a/jmh-core/src/main/java/org/openjdk/jmh/profile/ExternalProfiler.java	Thu May 29 15:55:27 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/profile/ExternalProfiler.java	Thu May 29 20:49:08 2014 +0400
@@ -33,7 +33,11 @@
  */
 public interface ExternalProfiler extends Profiler {
 
-    Collection<String> beforeTrial();
+    Collection<String> addJVMInvokeOptions();
+
+    Collection<String> addJVMOptions();
+
+    void beforeTrial();
 
     Collection<? extends Result> afterTrial();
 
--- a/jmh-core/src/main/java/org/openjdk/jmh/profile/ProfilerFactory.java	Thu May 29 15:55:27 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/profile/ProfilerFactory.java	Thu May 29 20:49:08 2014 +0400
@@ -44,6 +44,7 @@
         profs.add(HotspotRuntimeProfiler.class);
         profs.add(HotspotThreadProfiler.class);
         profs.add(StackProfiler.class);
+        profs.add(DummyExternalProfiler.class);
         return profs;
     }
 
@@ -96,7 +97,7 @@
         return null;
     }
 
-    public static Profiler prepareProfiler(Class<? extends InternalProfiler> klass, VerboseMode verboseMode) {
+    public static Profiler prepareProfiler(Class<? extends Profiler> klass, VerboseMode verboseMode) {
         try {
             return klass.newInstance();
         } catch (InstantiationException e) {
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/BaseMicroBenchmarkHandler.java	Thu May 29 15:55:27 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/BaseMicroBenchmarkHandler.java	Thu May 29 20:49:08 2014 +0400
@@ -97,8 +97,7 @@
         // register the profilers
         for (Class<? extends Profiler> prof : options.getProfilers()) {
             if (!ProfilerFactory.isInternal(prof)) continue;
-            Class<? extends InternalProfiler> intProf = (Class<? extends InternalProfiler>) prof;
-            list.add((InternalProfiler) ProfilerFactory.prepareProfiler(intProf, options.verbosity().orElse(Defaults.VERBOSITY)));
+            list.add((InternalProfiler) ProfilerFactory.prepareProfiler(prof, options.verbosity().orElse(Defaults.VERBOSITY)));
         }
         return list;
     }
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java	Thu May 29 15:55:27 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java	Thu May 29 20:49:08 2014 +0400
@@ -28,12 +28,14 @@
 import org.openjdk.jmh.annotations.Mode;
 import org.openjdk.jmh.link.BinaryLinkServer;
 import org.openjdk.jmh.logic.results.BenchResult;
+import org.openjdk.jmh.logic.results.Result;
 import org.openjdk.jmh.logic.results.RunResult;
 import org.openjdk.jmh.output.format.OutputFormat;
 import org.openjdk.jmh.output.format.OutputFormatFactory;
 import org.openjdk.jmh.output.results.ResultFormat;
 import org.openjdk.jmh.output.results.ResultFormatFactory;
 import org.openjdk.jmh.output.results.ResultFormatType;
+import org.openjdk.jmh.profile.ExternalProfiler;
 import org.openjdk.jmh.profile.Profiler;
 import org.openjdk.jmh.profile.ProfilerFactory;
 import org.openjdk.jmh.runner.options.Options;
@@ -387,7 +389,19 @@
 
             BenchmarkRecord benchmark = actionPlan.getMeasurementActions().get(0).getBenchmark();
 
-            String[] commandString = getSeparateExecutionCommand(benchmark, server.getHost(), server.getPort());
+            List<ExternalProfiler> profilers = new ArrayList<ExternalProfiler>();
+
+            List<String> javaInvokeOptions = new ArrayList<String>();
+            List<String> javaOptions = new ArrayList<String>();
+            for (Class<? extends Profiler> p : options.getProfilers()) {
+                if (!ProfilerFactory.isExternal(p)) continue;
+                ExternalProfiler prof = (ExternalProfiler) ProfilerFactory.prepareProfiler(p, null);
+                profilers.add(prof);
+                javaInvokeOptions.addAll(prof.addJVMInvokeOptions());
+                javaOptions.addAll(prof.addJVMOptions());
+            }
+
+            String[] commandString = getSeparateExecutionCommand(benchmark, server.getHost(), server.getPort(), javaInvokeOptions, javaOptions);
             String opts = merge(getJvmArgs(benchmark));
             if (opts.trim().isEmpty()) {
                 opts = "<none>";
@@ -417,7 +431,21 @@
                 out.println("# VM invoker: " + jvm);
                 out.println("# VM options: " + opts);
                 out.println("# Fork: " + (i + 1) + " of " + forkCount);
+
+                for (ExternalProfiler profiler : profilers) {
+                    profiler.beforeTrial();
+                }
+
                 Multimap<BenchmarkRecord, BenchResult> result = doFork(server, commandString);
+
+                for (ExternalProfiler profiler : profilers) {
+                    for (Result profR : profiler.afterTrial()) {
+                        for (BenchResult r : result.values()) {
+                            r.amend(profR);
+                        }
+                    }
+                }
+
                 results.merge(result);
                 afterBenchmark(benchmark);
             }
@@ -489,21 +517,29 @@
      * Helper method for assembling the command to execute the forked JVM with
      *
      *
+     *
      * @param benchmark benchmark to execute
      * @param host host VM host
      * @param port host VM port
-     * @return the final command to execute
+     * @param javaInvokeOptions
+     *@param javaOptions @return the final command to execute
      */
-    public String[] getSeparateExecutionCommand(BenchmarkRecord benchmark, String host, int port) {
+    public String[] getSeparateExecutionCommand(BenchmarkRecord benchmark, String host, int port, List<String> javaInvokeOptions, List<String> javaOptions) {
 
         List<String> command = new ArrayList<String>();
 
+        // prefix java invoke options, if any profiler wants it
+        command.addAll(javaInvokeOptions);
+
         // use supplied jvm, if given
         command.add(options.getJvm().orElse(getDefaultJvm()));
 
         // use supplied jvm args, if given
         command.addAll(getJvmArgs(benchmark));
 
+        // add profiler JVM commands, if any profiler wants it
+        command.addAll(javaOptions);
+
         // add any compiler oracle hints
         CompilerHints.addCompilerHints(command);
 
--- a/jmh-core/src/test/java/org/openjdk/jmh/runner/RunnerTest.java	Thu May 29 15:55:27 2014 +0400
+++ b/jmh-core/src/test/java/org/openjdk/jmh/runner/RunnerTest.java	Thu May 29 20:49:08 2014 +0400
@@ -24,19 +24,20 @@
  */
 package org.openjdk.jmh.runner;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+import org.openjdk.jmh.util.FileUtils;
 
 import java.io.File;
 import java.io.IOException;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
-import org.junit.Test;
-import org.openjdk.jmh.annotations.Mode;
-import org.openjdk.jmh.runner.options.OptionsBuilder;
-import org.openjdk.jmh.util.FileUtils;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 public class RunnerTest {
     private static final String DUMMY_HOST = "host";
@@ -52,7 +53,7 @@
     public void testEmptyOptsHaveCompileCommandFile() {
         Runner blade = new Runner(new OptionsBuilder());
         BenchmarkRecord benchmark = new BenchmarkRecord("Foo","bar",Mode.Throughput);
-        String[] command = blade.getSeparateExecutionCommand(benchmark, DUMMY_HOST, DUMMY_PORT);
+        String[] command = blade.getSeparateExecutionCommand(benchmark, DUMMY_HOST, DUMMY_PORT, Collections.<String>emptyList(), Collections.<String>emptyList());
 
         // expecting 1 compile command file
         List<String> files = CompilerHints.getCompileCommandFiles(Arrays.asList(command));
@@ -77,7 +78,7 @@
         Runner blade = new Runner(new OptionsBuilder().
                 jvmArgs(CompilerHints.XX_COMPILE_COMMAND_FILE + tempHints).build());
         BenchmarkRecord benchmark = new BenchmarkRecord("Foo","bar",Mode.Throughput);
-        String[] command = blade.getSeparateExecutionCommand(benchmark, DUMMY_HOST, DUMMY_PORT);
+        String[] command = blade.getSeparateExecutionCommand(benchmark, DUMMY_HOST, DUMMY_PORT, Collections.<String>emptyList(), Collections.<String>emptyList());
 
         // expecting 1 compile command file
         List<String> files = CompilerHints.getCompileCommandFiles(Arrays.asList(command));
@@ -107,7 +108,7 @@
                 jvmArgs(CompilerHints.XX_COMPILE_COMMAND_FILE + tempHints1,
                         CompilerHints.XX_COMPILE_COMMAND_FILE + tempHints2).build());
         BenchmarkRecord benchmark = new BenchmarkRecord("Foo","bar",Mode.Throughput);
-        String[] command = blade.getSeparateExecutionCommand(benchmark, DUMMY_HOST, DUMMY_PORT);
+        String[] command = blade.getSeparateExecutionCommand(benchmark, DUMMY_HOST, DUMMY_PORT, Collections.<String>emptyList(), Collections.<String>emptyList());
 
         // expecting 1 compile command file
         List<String> files = CompilerHints.getCompileCommandFiles(Arrays.asList(command));