changeset 402:0a7337dda90b

Switch to Commons Math percentile calculation instead of using the handwritten one.
author shade
date Mon, 17 Feb 2014 23:47:05 +0400
parents 0280e5a5d571
children 3e30ac7a685c
files jmh-core/src/main/java/org/openjdk/jmh/util/internal/ListStatistics.java jmh-core/src/main/java/org/openjdk/jmh/util/internal/MultisetStatistics.java jmh-core/src/test/java/org/openjdk/jmh/util/TestListStatistics.java jmh-core/src/test/java/org/openjdk/jmh/util/TestMultisetStatistics.java
diffstat 4 files changed, 73 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/jmh-core/src/main/java/org/openjdk/jmh/util/internal/ListStatistics.java	Mon Feb 17 22:51:19 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/util/internal/ListStatistics.java	Mon Feb 17 23:47:05 2014 +0400
@@ -24,8 +24,9 @@
  */
 package org.openjdk.jmh.util.internal;
 
+import org.apache.commons.math3.stat.descriptive.rank.Percentile;
+
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 
 /**
@@ -111,31 +112,17 @@
             return Double.NaN;
         }
 
-        Collections.sort(values);
-
-        int n1 = (int) Math.floor(rank / 100.0D * values.size());
-        int n2 = (int) Math.ceil(rank / 100.D * values.size());
-
-        if (n1 < 0) {
-            n1 = 0;
+        if (rank == 0) {
+            return getMin();
         }
 
-        if (n2 < 0) {
-            n2 = 0;
+        double[] vs = new double[values.size()];
+        for (int i = 0; i < values.size(); i++) {
+            vs[i] = values.get(i);
         }
 
-        if (n1 >= values.size()) {
-            n1 = values.size() - 1;
-        }
-
-        if (n2 >= values.size()) {
-            n2 = values.size() - 1;
-        }
-
-        double v1 = values.get(n1);
-        double v2 = values.get(n2);
-
-        return v1 + (v2 - v1) / 2;
+        Percentile p = new Percentile();
+        return p.evaluate(vs, rank);
     }
 
     @Override
--- a/jmh-core/src/main/java/org/openjdk/jmh/util/internal/MultisetStatistics.java	Mon Feb 17 22:51:19 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/util/internal/MultisetStatistics.java	Mon Feb 17 23:47:05 2014 +0400
@@ -24,6 +24,10 @@
  */
 package org.openjdk.jmh.util.internal;
 
+import org.apache.commons.math3.stat.descriptive.rank.Percentile;
+
+import java.util.Arrays;
+
 public class MultisetStatistics extends AbstractStatistics {
 
     private final Multiset<Double> values;
@@ -73,13 +77,19 @@
         if (rank < 0.0d || rank > 100.0d)
             throw new IllegalArgumentException("Rank should be within [0; 100]");
 
-        long thresh = (long) (values.size() * rank / 100.0);
-        long cur = 0;
+        if (rank == 0.0d) {
+            return getMin();
+        }
+
+        int cur = 0;
+        double[] vs = new double[values.size()];
         for (double d : values.keys()) {
+            Arrays.fill(vs, cur, cur + values.count(d), d);
             cur += values.count(d);
-            if (cur >= thresh) return d;
         }
-        return Double.NaN;
+
+        Percentile p = new Percentile();
+        return p.evaluate(vs, rank);
     }
 
     @Override
--- a/jmh-core/src/test/java/org/openjdk/jmh/util/TestListStatistics.java	Mon Feb 17 22:51:19 2014 +0400
+++ b/jmh-core/src/test/java/org/openjdk/jmh/util/TestListStatistics.java	Mon Feb 17 23:47:05 2014 +0400
@@ -137,6 +137,31 @@
         assertEquals(72.44402, interval[1], 0.002);
     }
 
+    @Test
+    public strictfp void testPercentile_00() {
+        assertEquals(2.345, instance.getPercentile(0), 0.002);
+    }
+
+    @Test
+    public strictfp void testPercentile_50() {
+        assertEquals(56.460, instance.getPercentile(50), 0.002);
+    }
+
+    @Test
+    public strictfp void testPercentile_90() {
+        assertEquals(93.044, instance.getPercentile(90), 0.002);
+    }
+
+    @Test
+    public strictfp void testPercentile_99() {
+        assertEquals(96.667, instance.getPercentile(99), 0.002);
+    }
+
+    @Test
+    public strictfp void testPercentile_100() {
+        assertEquals(96.667, instance.getPercentile(100), 0.002);
+    }
+
     /**
      * Test of toString, of class Statistics
      */
--- a/jmh-core/src/test/java/org/openjdk/jmh/util/TestMultisetStatistics.java	Mon Feb 17 22:51:19 2014 +0400
+++ b/jmh-core/src/test/java/org/openjdk/jmh/util/TestMultisetStatistics.java	Mon Feb 17 23:47:05 2014 +0400
@@ -138,6 +138,31 @@
         assertEquals(72.44402, interval[1], 0.002);
     }
 
+    @Test
+    public strictfp void testPercentile_00() {
+        assertEquals(2.345, instance.getPercentile(0), 0.002);
+    }
+
+    @Test
+    public strictfp void testPercentile_50() {
+        assertEquals(56.460, instance.getPercentile(50), 0.002);
+    }
+
+    @Test
+    public strictfp void testPercentile_90() {
+        assertEquals(93.044, instance.getPercentile(90), 0.002);
+    }
+
+    @Test
+    public strictfp void testPercentile_99() {
+        assertEquals(96.667, instance.getPercentile(99), 0.002);
+    }
+
+    @Test
+    public strictfp void testPercentile_100() {
+        assertEquals(96.667, instance.getPercentile(100), 0.002);
+    }
+
     /**
      * Test of toString, of class Statistics
      */