changeset 1190:36437173192a

7901374: NPE when processing -prof gc results
author shade
date Tue, 07 Apr 2015 13:01:26 +0300
parents b20cbf08bfaa
children 1898f77c754c
files jmh-core/src/main/java/org/openjdk/jmh/profile/GCProfiler.java jmh-core/src/main/java/org/openjdk/jmh/results/BenchmarkResult.java jmh-core/src/test/java/org/openjdk/jmh/results/TestBenchmarkResult.java
diffstat 3 files changed, 109 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/jmh-core/src/main/java/org/openjdk/jmh/profile/GCProfiler.java	Mon Apr 06 22:43:03 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/profile/GCProfiler.java	Tue Apr 07 13:01:26 2015 +0300
@@ -45,10 +45,8 @@
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 public class GCProfiler implements InternalProfiler {
@@ -56,11 +54,9 @@
     private long beforeGCCount;
     private long beforeGCTime;
     private final NotificationListener listener;
-    private final Set<String> observedSpaces;
     private volatile Multiset<String> churn;
 
     public GCProfiler() {
-        observedSpaces = new HashSet<String>();
         churn = new HashMultiset<String>();
 
         NotificationListener listener = null;
@@ -88,7 +84,6 @@
                                 long c = before.getUsed() - after.getUsed();
                                 if (c > 0) {
                                     churn.add(name, c);
-                                    observedSpaces.add(name);
                                 }
                             }
                         }
@@ -166,7 +161,7 @@
                 "ms",
                 AggregationPolicy.SUM));
 
-        for (String space : observedSpaces) {
+        for (String space : churn.keys()) {
             double churnRate = 1.0 * churn.count(space) * TimeUnit.SECONDS.toNanos(1) / (afterTime - beforeTime);
 
             results.add(new ProfilerResult(
--- a/jmh-core/src/main/java/org/openjdk/jmh/results/BenchmarkResult.java	Mon Apr 06 22:43:03 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/results/BenchmarkResult.java	Tue Apr 07 13:01:26 2015 +0300
@@ -80,19 +80,24 @@
     }
 
     public Result getPrimaryResult() {
-        @SuppressWarnings("unchecked")
-        Aggregator<Result> aggregator = iterationResults.iterator().next().getPrimaryResult().getIterationAggregator();
-
+        Aggregator<Result> aggregator = null;
         Collection<Result> aggrs = new ArrayList<Result>();
         for (IterationResult r : iterationResults) {
-            aggrs.add(r.getPrimaryResult());
+            Result e = r.getPrimaryResult();
+            aggrs.add(e);
+            aggregator = e.getIterationAggregator();
         }
         for (Result r : benchmarkResults.values()) {
             if (r.getRole().isPrimary()) {
                 aggrs.add(r);
             }
         }
-        return aggregator.aggregate(aggrs);
+
+        if (aggregator != null) {
+            return aggregator.aggregate(aggrs);
+        } else {
+            throw new IllegalStateException("No aggregator for primary result");
+        }
     }
 
     public Map<String, Result> getSecondaryResults() {
@@ -103,27 +108,31 @@
 
         Map<String, Result> answers = new TreeMap<String, Result>();
         for (String label : labels) {
-            @SuppressWarnings("unchecked")
-            Aggregator<Result> aggregator = iterationResults.iterator().next().getSecondaryResults().get(label).getIterationAggregator();
-
+            Aggregator<Result> aggregator = null;
             Collection<Result> results = new ArrayList<Result>();
             for (IterationResult r : iterationResults) {
-                results.add(r.getSecondaryResults().get(label));
+                Result e = r.getSecondaryResults().get(label);
+                if (e != null) {
+                    results.add(e);
+                    aggregator = e.getIterationAggregator();
+                }
             }
-            answers.put(label, aggregator.aggregate(results));
+
+            if (aggregator != null) {
+                answers.put(label, aggregator.aggregate(results));
+            }
         }
 
         for (String label : benchmarkResults.keys()) {
-            @SuppressWarnings("unchecked")
-            Aggregator<Result> aggregator = benchmarkResults.get(label).iterator().next().getIterationAggregator();
-
+            Aggregator<Result> aggregator = null;
             Collection<Result> results = new ArrayList<Result>();
             for (Result r : benchmarkResults.get(label)) {
                 if (r.getRole().isSecondary()) {
                     results.add(r);
+                    aggregator = r.getIterationAggregator();
                 }
             }
-            if (!results.isEmpty()) {
+            if (aggregator != null) {
                 answers.put(label, aggregator.aggregate(results));
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/test/java/org/openjdk/jmh/results/TestBenchmarkResult.java	Tue Apr 07 13:01:26 2015 +0300
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, 2015, 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.results;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.util.ListStatistics;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+
+public class TestBenchmarkResult {
+
+    @Test
+    public void testMissingSecondaries() {
+        IterationResult ir1 = new IterationResult(null, null, null);
+        ir1.addResult(new SecondaryResult("label1", 1));
+        IterationResult ir2 = new IterationResult(null, null, null);
+        ir2.addResult(new SecondaryResult("label2", 2));
+        IterationResult ir3 = new IterationResult(null, null, null);
+        ir3.addResult(new SecondaryResult("label2", 3));
+        BenchmarkResult br = new BenchmarkResult(null, Arrays.asList(ir1, ir2, ir3));
+
+        Map<String, Result> sr = br.getSecondaryResults();
+        Assert.assertEquals(2, sr.size());
+        Assert.assertEquals(1.0D, sr.get("label1").getScore(), 0.001);
+        Assert.assertEquals(5.0D, sr.get("label2").getScore(), 0.001);
+    }
+
+    public static class SecondaryResult extends Result<SecondaryResult> {
+        public SecondaryResult(String label, double val) {
+            super(ResultRole.SECONDARY, label, of(val), "unit", AggregationPolicy.SUM);
+        }
+
+        protected Aggregator<SecondaryResult> getThreadAggregator() {
+            return new SecondaryResultAggregator();
+        }
+
+        @Override
+        protected Aggregator<SecondaryResult> getIterationAggregator() {
+            return new SecondaryResultAggregator();
+        }
+    }
+
+    public static class SecondaryResultAggregator implements Aggregator<SecondaryResult> {
+        @Override
+        public SecondaryResult aggregate(Collection<SecondaryResult> results) {
+            String label = null;
+            ListStatistics s = new ListStatistics();
+            for (SecondaryResult r : results) {
+                if (label == null) {
+                    label = r.getLabel();
+                } else {
+                    Assert.assertEquals(label, r.getLabel());
+                }
+                s.addValue(r.getScore());
+            }
+            return new SecondaryResult(label, s.getSum());
+        }
+    }
+
+}