changeset 218:c9aaa83494f4

High-definition histogram to collect samples.
author shade
date Wed, 30 Oct 2013 20:57:52 +0400
parents 4660959c5cef
children a49f57481f14
files jmh-core/src/main/java/org/openjdk/jmh/logic/results/SampleTimePerOp.java jmh-core/src/main/java/org/openjdk/jmh/util/internal/SampleBuffer.java
diffstat 2 files changed, 43 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/jmh-core/src/main/java/org/openjdk/jmh/logic/results/SampleTimePerOp.java	Wed Oct 30 12:15:55 2013 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/logic/results/SampleTimePerOp.java	Wed Oct 30 20:57:52 2013 +0400
@@ -25,7 +25,6 @@
 package org.openjdk.jmh.logic.results;
 
 import org.openjdk.jmh.runner.parameters.TimeValue;
-import org.openjdk.jmh.util.internal.BootstrappedStatistics;
 import org.openjdk.jmh.util.internal.SampleBuffer;
 import org.openjdk.jmh.util.internal.Statistics;
 
@@ -69,20 +68,12 @@
     /** {@inheritDoc} */
     @Override
     public double getScore() {
-        Statistics stats = new Statistics();
-        for (long l : buffer.getSamples()) {
-            stats.addValue(l);
-        }
-        return convertNs(stats.getMean());
+        return convertNs(buffer.getStatistics().getMean());
     }
 
     @Override
     public Statistics getStatistics() {
-        Statistics stats = new Statistics();
-        for (long l : buffer.getSamples()) {
-            stats.addValue(convertNs(l));
-        }
-        return stats;
+        return buffer.getStatistics();
     }
 
     @Override
@@ -97,10 +88,7 @@
 
     @Override
     public String toString() {
-        Statistics stats = new Statistics();
-        for (long l : buffer.getSamples()) {
-            stats.addValue(l);
-        }
+        Statistics stats = buffer.getStatistics();
 
         StringBuilder sb = new StringBuilder();
         sb.append("n = ").append(stats.getN()).append(", ");
@@ -122,11 +110,7 @@
 
     @Override
     public String extendedInfo(String label) {
-
-        Statistics stats = new Statistics();
-        for (long l : buffer.getSamples()) {
-            stats.addValue(l);
-        }
+        Statistics stats = buffer.getStatistics();
 
         StringBuilder sb = new StringBuilder();
         sb.append("Run result ").append((label == null) ? "" : "\"" + label + "\"").append(": \n");
@@ -149,18 +133,10 @@
 
         sb.append(String.format("        min = %10.3f %s\n", convertNs(stats.getMin()), getScoreUnit()));
 
-        BootstrappedStatistics boot = new BootstrappedStatistics(stats);
         for (double p : new double[] {Double.MIN_VALUE, 0.50, 0.90, 0.95, 0.99, 0.999, 0.9999, 1.00}) {
-            Statistics bootedStat = boot.getBootPercentile(p*100);
-
-            double[] interval95 = bootedStat.getConfidenceInterval(0.05);
-            double[] interval99 = bootedStat.getConfidenceInterval(0.01);
-
-            sb.append(String.format("  %9s = %10.3f \u00B1(95%%) %.3f \u00B1(99%%) %.3f %s\n",
+            sb.append(String.format("  %9s = %10.3f %s\n",
                     "p(" + String.format("%.4f", p) + ")",
-                    convertNs(bootedStat.getMean()),
-                    convertNs((interval95[1] - interval95[0]) / 2),
-                    convertNs((interval99[1] - interval99[0]) / 2),
+                    convertNs(stats.getPercentile(p*100)),
                     getScoreUnit()
             ));
         }
@@ -186,21 +162,15 @@
 
         @Override
         public Result aggregate(Collection<SampleTimePerOp> results) {
-            // estimate size
-            int size = 0;
-            for (SampleTimePerOp r : results) {
-                size += r.buffer.getSamples().length;
-            }
-
             // generate new sample buffer
             ResultRole mode = null;
             String label = null;
-            SampleBuffer buffer = new SampleBuffer(size);
+            SampleBuffer buffer = new SampleBuffer();
             TimeUnit tu = null;
             for (SampleTimePerOp r : results) {
                 tu = r.outputTimeUnit;
                 label = r.label;
-                buffer.addAll(r.buffer.getSamples());
+                buffer.addAll(r.buffer);
             }
 
             return new SampleTimePerOp(mode, label, buffer, tu);
--- a/jmh-core/src/main/java/org/openjdk/jmh/util/internal/SampleBuffer.java	Wed Oct 30 12:15:55 2013 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/util/internal/SampleBuffer.java	Wed Oct 30 20:57:52 2013 +0400
@@ -25,7 +25,6 @@
 package org.openjdk.jmh.util.internal;
 
 import java.io.Serializable;
-import java.util.Arrays;
 
 /**
  * Sampling buffer accepts samples.
@@ -34,38 +33,56 @@
  */
 public class SampleBuffer implements Serializable {
 
-    private final long[] samples;
-    private final int size;
-    private int index;
+    private static final int PRECISION_BITS = 10;
+    private static final int SIZE_LIMIT = 1000000;
+
+    private final int[][] hdr;
+
+    private int size;
 
     public SampleBuffer() {
-        this(1024);
+        hdr = new int[64][];
+        clear();
     }
 
-    public SampleBuffer(int size) {
-        this.size = size;
-        this.samples = new long[size];
+    private void clear() {
+        for (int p = 0; p < 64; p++) {
+            hdr[p] = new int[1 << PRECISION_BITS];
+        }
+        size = 0;
     }
 
     public boolean add(long sample) {
-        if (index == size) {
-            samples[0] = sample;
-            index = 0;
+        if (size++ > SIZE_LIMIT) {
+            clear();
             return true;
         } else {
-            samples[index++] = sample;
+            int msb = 64 - Long.numberOfLeadingZeros(sample);
+            int bucket = Math.max(0, msb - PRECISION_BITS);
+            int subBucket = (int) (sample >> bucket);
+            hdr[bucket][subBucket]++;
             return false;
         }
     }
 
-    public long[] getSamples() {
-        return Arrays.copyOf(samples, index);
+    public Statistics getStatistics() {
+        // TODO: This method is very memory-hungry, make the specialized Statistics
+        Statistics stat = new Statistics();
+        for (int i = 0; i < hdr.length; i++) {
+            for (int j = 0; j < hdr[i].length; j++) {
+                for (int c = 0; c < hdr[i][j]; c++) {
+                    stat.addValue(j << i);
+                }
+            }
+        }
+        return stat;
     }
 
-    public void addAll(long[] samples) {
-        for (long l : samples) {
-            add(l);
+    public void addAll(SampleBuffer other) {
+        for (int i = 0; i < other.hdr.length; i++) {
+            for (int j = 0; j < other.hdr[i].length; j++) {
+                hdr[i][j] += other.hdr[i][j];
+            }
         }
     }
-
 }