Przeglądaj źródła

new: BenchmarkRunner
new: BenchmarkReport

Ranides Atterwim 10 lat temu
rodzic
commit
efe87e30c3

+ 5 - 0
assira.junit/pom.xml

@@ -26,5 +26,10 @@
             <artifactId>junit</artifactId>
             <version>4.10</version>
         </dependency>
+        <dependency>
+            <groupId>net.ranides</groupId>
+            <artifactId>caliper</artifactId>
+            <version>1.0L</version>
+        </dependency>
     </dependencies>
 </project>

+ 104 - 0
assira.junit/src/main/java/net/ranides/assira/junit/BenchmarkReport.java

@@ -0,0 +1,104 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.junit;
+
+import java.io.PrintStream;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @todo (assira.junit # 4) BenchmarkReport: usunąć obsługę params
+ */
+public final class BenchmarkReport {
+    
+    private static final Pattern RE_BENCHMARK = Pattern.compile(
+        "\\{vm=(.+?), trial=(.+?), benchmark=(.+?)\\} ([0-9,]+) ns; \\?=([0-9,]+) ns @ ([0-9]+) trials"
+    );
+    
+    private BenchmarkReport() { /* utility class */ }
+    
+    public static void print(PrintStream out, String data) {
+        
+        InfoMap result = new InfoMap();
+        for(String line : data.split("[\\n\\r]+")) {
+            result.add(line);
+        }
+        
+        String pattern = MessageFormat.format("%-{0}s    = %{1}.0f ? %.0f%n", 
+            result.maxname,
+            String.valueOf((int)result.maxtime).length()
+        );
+                
+        for(List<Info> binfo : result.map.values()) {
+            int trials = binfo.size();
+            double avg = 0;
+            double dev = 0;
+            for(Info info : binfo) {
+                avg += info.time;
+            }
+            avg = avg / trials;
+
+            for(Info info : binfo) {
+                dev += (avg - info.time) * (avg - info.time);
+            }
+            dev = Math.sqrt(dev);
+            out.printf(pattern, binfo.get(0).name, avg, dev);
+        }
+    }
+
+    private static class InfoMap {
+        
+        private final Map<String, List<Info>> map = new TreeMap<>();
+        
+        public int maxname = 20;
+        public double maxtime = 0;
+        
+        public void add(String line) {
+            Matcher hit = RE_BENCHMARK.matcher(line);
+            if(hit.find()) {
+                add(new Info(hit));
+            }
+        }
+        
+        public void add(Info info) {
+            maxname = Math.max(maxname, info.name.length());
+            maxtime = Math.max(maxtime, info.time);
+            
+            if( !map.containsKey(info.name) ) {
+                map.put(info.name, new ArrayList<>());
+            }
+            map.get(info.name).add(info);
+        }
+        
+    }
+    
+    private static class Info {
+        
+        public final String vm;
+        public final String name;
+        public final String trial;
+        public final double time;
+        public final double timeDev;
+        
+        public Info(Matcher hit) {
+            this.vm = hit.group(1);
+            this.name = hit.group(3);
+            this.trial = hit.group(2);
+            this.time = Double.parseDouble(hit.group(4).replace(',', '.'));
+            this.timeDev = Double.parseDouble(hit.group(5).replace(',', '.'));
+        }
+
+    }
+
+}

+ 102 - 0
assira.junit/src/main/java/net/ranides/assira/junit/BenchmarkRunner.java

@@ -0,0 +1,102 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira.junit
+ */
+package net.ranides.assira.junit;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.IllegalCharsetNameException;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public final class BenchmarkRunner {
+    
+    private BenchmarkRunner() {
+        // utility class
+    }
+    
+    public static void run(Class<?> clazz) {
+        OutputStream collector = ConsoleObserver.get();
+        new com.google.caliper.Runner().run(
+            "--trials", "3",
+//            "--warmupMillis", "100",
+//            "--runMillis", "100",
+//            "-Dparam=0",
+            clazz.getName()
+        );
+        BenchmarkReport.print(System.out, collector.toString());
+    }
+    
+    
+    static final class ConsoleObserver extends OutputStream {
+
+        private final PrintStream stdout;
+        private final ByteArrayOutputStream stream;
+
+        private ConsoleObserver(PrintStream stdout) {
+            this.stdout = stdout;
+            this.stream = new ByteArrayOutputStream();
+        }
+
+        public static ConsoleObserver get() {
+            ConsoleObserver observer = new ConsoleObserver(System.out);
+            System.setOut(new PrintStream(observer));
+            return observer;
+        }
+
+        @Override
+        public void write(int data) throws IOException {
+            stdout.write(data);
+            stream.write(data);
+        }
+
+        @Override
+        public void write(byte[] data) throws IOException {
+            stdout.write(data);
+            stream.write(data);
+        }
+
+        @Override
+        public void write(byte[] data, int offset, int length) throws IOException {
+            stdout.write(data, offset, length);
+            stream.write(data, offset, length);
+        }
+
+        @Override
+        public void close() throws IOException {
+            stream.close();
+            System.setOut(stdout);
+        }
+
+        @Override
+        public void flush() throws IOException {
+            stdout.flush();
+            stream.flush();
+        }
+
+        @Override
+        public String toString() {
+            return toString("UTF-8");
+        }
+
+        public String toString(String charset) throws IllegalCharsetNameException {
+            try {
+                return stream.toString(charset);
+            } catch (UnsupportedEncodingException cause) {
+                throw (IllegalCharsetNameException)new IllegalCharsetNameException(charset).initCause(cause);
+            }
+        }
+
+    }
+
+
+}
+

+ 65 - 0
assira.junit/src/test/java/net/ranides/assira/junit/BenchmarkReportTest.java

@@ -0,0 +1,65 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/???
+ */
+package net.ranides.assira.junit;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public class BenchmarkReportTest {
+    
+    private static final String INPUT =
+        "     0% Scenario{vm=java, trial=0, benchmark=ListThread} 12741,34 ns; ?=252,99 ns @ 10 trials\n"+
+        "    4% Scenario{vm=java, trial=1, benchmark=ListThread} 12735,86 ns; ?=29,81 ns @ 3 trials\n"+
+        "    8% Scenario{vm=java, trial=2, benchmark=ListThread} 12624,55 ns; ?=70,86 ns @ 3 trials\n"+
+        "   13% Scenario{vm=java, trial=0, benchmark=CallerThread} 13616,58 ns; ?=36,58 ns @ 3 trials\n"+
+        "   17% Scenario{vm=java, trial=1, benchmark=CallerThread} 13677,01 ns; ?=66,01 ns @ 3 trials\n"+
+        "   21% Scenario{vm=java, trial=2, benchmark=CallerThread} 13852,23 ns; ?=63,15 ns @ 3 trials\n"+
+        "   25% Scenario{vm=java, trial=0, benchmark=CallerSecurityManager} 826,64 ns; ?=1,84 ns @ 3 trials\n"+
+        "   29% Scenario{vm=java, trial=1, benchmark=CallerSecurityManager} 816,69 ns; ?=3,84 ns @ 3 trials\n"+
+        "   33% Scenario{vm=java, trial=2, benchmark=CallerSecurityManager} 817,24 ns; ?=3,19 ns @ 3 trials\n"+
+        "   38% Scenario{vm=java, trial=0, benchmark=CallerSunReflect} 142,74 ns; ?=1,38 ns @ 5 trials\n"+
+        "   42% Scenario{vm=java, trial=1, benchmark=CallerSunReflect} 145,95 ns; ?=1,77 ns @ 10 trials\n"+
+        "   46% Scenario{vm=java, trial=2, benchmark=CallerSunReflect} 143,09 ns; ?=1,15 ns @ 3 trials\n"+
+        "   50% Scenario{vm=java, trial=0, benchmark=ListException} 12035,15 ns; ?=43,56 ns @ 3 trials\n"+
+        "   54% Scenario{vm=java, trial=1, benchmark=ListException} 12095,09 ns; ?=109,92 ns @ 3 trials\n"+
+        "   58% Scenario{vm=java, trial=2, benchmark=ListException} 12086,37 ns; ?=65,36 ns @ 3 trials\n"+
+        "   63% Scenario{vm=java, trial=0, benchmark=CallerException} 12985,63 ns; ?=145,23 ns @ 10 trials\n"+
+        "   67% Scenario{vm=java, trial=1, benchmark=CallerException} 12959,19 ns; ?=63,32 ns @ 3 trials\n"+
+        "   71% Scenario{vm=java, trial=2, benchmark=CallerException} 12881,98 ns; ?=68,18 ns @ 3 trials\n"+
+        "   75% Scenario{vm=java, trial=0, benchmark=ListSunReflect} 3754,91 ns; ?=37,69 ns @ 4 trials\n"+
+        "   79% Scenario{vm=java, trial=1, benchmark=ListSunReflect} 3862,52 ns; ?=37,97 ns @ 7 trials\n"+
+        "   83% Scenario{vm=java, trial=2, benchmark=ListSunReflect} 3883,26 ns; ?=29,84 ns @ 3 trials\n"+
+        "   88% Scenario{vm=java, trial=0, benchmark=ListSecurityManager} 815,23 ns; ?=1,44 ns @ 3 trials\n"+
+        "   92% Scenario{vm=java, trial=1, benchmark=ListSecurityManager} 821,71 ns; ?=8,04 ns @ 3 trials\n"+
+        "   96% Scenario{vm=java, trial=2, benchmark=ListSecurityManager} 814,32 ns; ?=2,53 ns @ 3 trials\n";
+    
+    private static final String EXPECTED = 
+        "CallerException          = 12942 ? 76%n"+
+        "CallerSecurityManager    =   820 ? 8%n"+
+        "CallerSunReflect         =   144 ? 2%n"+
+        "CallerThread             = 13715 ? 173%n"+
+        "ListException            = 12072 ? 46%n"+
+        "ListSecurityManager      =   817 ? 6%n"+
+        "ListSunReflect           =  3834 ? 97%n"+
+        "ListThread               = 12701 ? 93%n";
+    
+    @Test
+    public void testManual() {
+        ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+        BenchmarkReport.print(new PrintStream(ostream), INPUT);
+
+//        System.out.printf(">>>%n%s<<<%n", ostream.toString());
+        assertEquals(String.format(EXPECTED), ostream.toString());
+    }
+    
+}