You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2016/02/04 00:27:52 UTC

[math] Improved formatting of the benchmarking report.

Repository: commons-math
Updated Branches:
  refs/heads/master 0952cee35 -> e0b2c86c8


Improved formatting of the benchmarking report.


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/e0b2c86c
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/e0b2c86c
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/e0b2c86c

Branch: refs/heads/master
Commit: e0b2c86c8754312d1e89307fbf84e6efbfa9fe0b
Parents: 0952cee
Author: Gilles <er...@apache.org>
Authored: Thu Feb 4 00:25:56 2016 +0100
Committer: Gilles <er...@apache.org>
Committed: Thu Feb 4 00:25:56 2016 +0100

----------------------------------------------------------------------
 .../org/apache/commons/math4/PerfTestUtils.java | 127 +++++++++++++++++--
 1 file changed, 119 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/e0b2c86c/src/test/java/org/apache/commons/math4/PerfTestUtils.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math4/PerfTestUtils.java b/src/test/java/org/apache/commons/math4/PerfTestUtils.java
index 7af8088..2064f53 100644
--- a/src/test/java/org/apache/commons/math4/PerfTestUtils.java
+++ b/src/test/java/org/apache/commons/math4/PerfTestUtils.java
@@ -16,12 +16,16 @@
  */
 package org.apache.commons.math4;
 
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.regex.MatchResult;
 import java.util.concurrent.Callable;
 
 import org.apache.commons.math4.util.MathArrays;
 import org.apache.commons.math4.random.RandomGenerator;
 import org.apache.commons.math4.random.Well19937c;
 import org.apache.commons.math4.exception.MathIllegalStateException;
+import org.apache.commons.math4.exception.NumberIsTooLargeException;
 import org.apache.commons.math4.exception.util.LocalizedFormats;
 import org.apache.commons.math4.stat.descriptive.StatisticalSummary;
 import org.apache.commons.math4.stat.descriptive.SummaryStatistics;
@@ -30,6 +34,18 @@ import org.apache.commons.math4.stat.descriptive.SummaryStatistics;
  * Simple benchmarking utilities.
  */
 public class PerfTestUtils {
+    /** Formatting. */
+    private static final int DEFAULT_MAX_NAME_WIDTH = 45;
+    /** Formatting. */
+    private static final String ELLIPSIS = "...";
+    /** Formatting. */
+    private static final String TO_STRING_MEMORY_ADDRESS_REGEX = "@\\p{XDigit}{1,8}";
+    /** Formatting. */
+    private static final String JAVA_IDENTIFIER_REGEX =
+        "(\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*\\.)*\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*";
+    /** Formatting. */
+    private static final Pattern JAVA_IDENTIFIER_PATTERN =
+        Pattern.compile(JAVA_IDENTIFIER_REGEX);
     /** Nanoseconds to milliseconds conversion factor ({@value}). */
     public static final double NANO_TO_MILLI = 1e-6;
     /** Default number of code repeat per timed block. */
@@ -159,6 +175,7 @@ public class PerfTestUtils {
      * {@link #time(int,int,boolean,Callable[]) time} method.
      *
      * @param title Title of the test (for the report).
+     * @param maxNameWidth Maximum width of the first column of the report.
      * @param repeatChunk Each timing measurement will done done for that
      * number of repeats of the code.
      * @param repeatStat Timing will be averaged over that number of runs.
@@ -172,6 +189,7 @@ public class PerfTestUtils {
      */
     @SuppressWarnings("boxing")
     public static StatisticalSummary[] timeAndReport(String title,
+                                                     int maxNameWidth,
                                                      int repeatChunk,
                                                      int repeatStat,
                                                      boolean runGC,
@@ -179,20 +197,26 @@ public class PerfTestUtils {
         // Header format.
         final String hFormat = "%s (calls per timed block: %d, timed blocks: %d, time unit: ms)";
 
+        // TODO: user-defined parameter?
+        final boolean removePackageName = false;
+
         // Width of the longest name.
         int nameLength = 0;
         for (RunTest m : methods) {
-            int len = m.getName().length();
+            int len = shorten(m.getName(), removePackageName).length();
             if (len > nameLength) {
                 nameLength = len;
             }
         }
-        final String nameLengthFormat = "%" + nameLength + "s";
+        final int actualNameLength = nameLength < maxNameWidth ?
+            nameLength :
+            maxNameWidth;
+        final String nameLengthFormat = "%" + actualNameLength + "s";
 
         // Column format.
-        final String cFormat = nameLengthFormat + " %14s %14s %10s %10s %15s";
+        final String cFormat = nameLengthFormat + " %9s %7s %10s %5s %4s %10s";
         // Result format.
-        final String format = nameLengthFormat + " %.8e %.8e %.4e %.4e % .8e";
+        final String format = nameLengthFormat + " %.3e %.1e %.4e %.3f %.2f %.4e";
 
         System.out.println(String.format(hFormat,
                                          title,
@@ -201,9 +225,10 @@ public class PerfTestUtils {
         System.out.println(String.format(cFormat,
                                          "name",
                                          "time/call",
-                                         "std error",
+                                         "std dev",
                                          "total time",
                                          "ratio",
+                                         "cv",
                                          "difference"));
         final StatisticalSummary[] time = time(repeatChunk,
                                                repeatStat,
@@ -213,12 +238,18 @@ public class PerfTestUtils {
         for (int i = 0, max = time.length; i < max; i++) {
             final StatisticalSummary s = time[i];
             final double sum = s.getSum() * repeatChunk;
+            final double mean = s.getMean();
+            final double sigma = s.getStandardDeviation();
             System.out.println(String.format(format,
-                                             methods[i].getName(),
-                                             s.getMean(),
-                                             s.getStandardDeviation(),
+                                             truncate(shorten(methods[i].getName(),
+                                                              removePackageName),
+                                                      actualNameLength,
+                                                      ELLIPSIS),
+                                             mean,
+                                             sigma,
                                              sum,
                                              sum / refSum,
+                                             sigma / mean,
                                              sum - refSum));
         }
 
@@ -240,6 +271,7 @@ public class PerfTestUtils {
     public static StatisticalSummary[] timeAndReport(String title,
                                                      RunTest ... methods) {
         return timeAndReport(title,
+                             DEFAULT_MAX_NAME_WIDTH,
                              DEFAULT_REPEAT_CHUNK,
                              DEFAULT_REPEAT_STAT,
                              false,
@@ -269,4 +301,83 @@ public class PerfTestUtils {
         /** {@inheritDoc} */
         public abstract Double call() throws Exception;
     }
+
+    /**
+     * Truncates a string so that it will not be longer than the
+     * specified length.
+     *
+     * @param str String to truncate.
+     * @param maxLength Maximum length.
+     * @param ellipsis String to use in place of the part being removed
+     * from the original string.
+     * @return the truncated string.
+     * @throws NumberIsTooLargeException if the length of {@code ellipsis}
+     * is larger than {@code maxLength - 2}.
+     */
+    private static String truncate(String str,
+                                   int maxLength,
+                                   String ellipsis) {
+        final int ellSize = ellipsis.length();
+        if (ellSize > maxLength - 2) {
+            throw new NumberIsTooLargeException(ellSize, maxLength - 2, false);
+        }
+
+        final int strSize = str.length();
+        if (strSize <= maxLength) {
+            // Size is OK.
+            return str;
+        }
+
+        return str.substring(0, maxLength - ellSize) + ellipsis;
+    }
+
+    /**
+     * Shortens a string.
+     * It will shorten package names and remove memory addresses
+     * that appear in an instance's name.
+     *
+     * @param str Orginal string.
+     * @param removePackageName Whether package name part of a
+     * fully-quallified name should be removed entirely.
+     * @return the shortened string.
+     */
+    private static String shorten(String str,
+                                  boolean removePackageName) {
+        final Matcher m = JAVA_IDENTIFIER_PATTERN.matcher(str);
+        final StringBuffer sb = new StringBuffer();
+        while (m.find()) {
+            final MatchResult r = m.toMatchResult();
+            m.appendReplacement(sb, shortenPackageName(r.group(),
+                                                       removePackageName));
+        }
+        m.appendTail(sb);
+
+        return sb.toString().replaceAll(TO_STRING_MEMORY_ADDRESS_REGEX, "");
+    }
+
+    /**
+     * Shortens package part of the name of a class.
+     *
+     * @param name Class name.
+     * @param remove Whether package name part of a fully-qualified
+     * name should be removed entirely.
+     * @return the shortened name.
+     */
+    private static String shortenPackageName(String name,
+                                             boolean remove) {
+        final String[] comp = name.split("\\.");
+        final int last = comp.length - 1;
+
+        if (remove) {
+            return comp[last];
+        }
+
+        final StringBuilder s = new StringBuilder();
+        for (int i = 0; i < last; i++) {
+            s.append(comp[i].substring(0, 1)).append(".");
+        }
+        s.append(comp[last]);
+
+        return s.toString();
+    }
 }