1/*
2 * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 *   - Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 *
11 *   - Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 *
15 *   - Neither the name of Oracle nor the names of its
16 *     contributors may be used to endorse or promote products derived
17 *     from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 * This source code is provided to illustrate the usage of a given feature
34 * or technique and has been deliberately simplified. Additional steps
35 * required for a production-quality application, such as security checks,
36 * input validation and proper error handling, might not be present in
37 * this sample code.
38 */
39
40
41package j2dbench.report;
42
43import java.io.*;
44import java.text.DecimalFormat;
45import java.util.*;
46import j2dbench.report.J2DAnalyzer.ResultHolder;
47import j2dbench.report.J2DAnalyzer.ResultSetHolder;
48
49/**
50 * This simple utility generates a wiki- or html-formatted table, which
51 * compares the performance of various image loading routines (relative
52 * to the core Image I/O plugins).
53 */
54public class IIOComparator {
55
56    private static final DecimalFormat decimalFormat =
57        new DecimalFormat("0.0");
58
59    /**
60     * List of methods, given in the order we want them to appear in
61     * the printed columns.
62     */
63    private static final String[] methodKeys = new String[] {
64        "IIO-Core", "IIO-Ext", "Toolkit", "JPEGCodec", "GdkPixBuf"
65    };
66
67    private static final Hashtable allResults = new Hashtable();
68
69    private static boolean wikiStyle;
70
71    private static void printIIOTable(String resultsFile) {
72        try {
73            J2DAnalyzer.readResults(resultsFile);
74        } catch (Exception e) {
75            System.err.println("Error reading results file: " +
76                               e.getMessage());
77            return;
78        }
79
80        Vector results = J2DAnalyzer.results;
81        int numsets = results.size();
82
83        ResultSetHolder base = (ResultSetHolder)results.elementAt(0);
84        Enumeration basekeys = base.getKeyEnumeration();
85        String[] keys = toSortedArray(basekeys, false);
86
87        // build results table
88        for (int k = 0; k < keys.length; k++) {
89            String key = keys[k];
90            ResultHolder rh = base.getResultByKey(key);
91            double score = rh.getScore();
92            Hashtable opts = rh.getOptions();
93
94            String imgsize = (String)opts.get("imageio.opts.size");
95            String content = (String)opts.get("imageio.opts.content");
96            String testname = "size=" + imgsize + ",content=" + content;
97
98            String format = null;
99            String method = null;
100            String name = rh.getName();
101            if (name.equals("imageio.input.image.imageio.reader.tests.read")) {
102                format = (String)opts.get("imageio.input.image.imageio.opts.format");
103                String type = format.substring(0, format.indexOf('-'));
104                format = format.substring(format.indexOf('-')+1);
105                if (format.equals("jpeg")) {
106                    format = "jpg";
107                }
108                method = "IIO-" + (type.equals("core") ? "Core" : "Ext");
109            } else if (name.equals("imageio.input.image.toolkit.tests.createImage")) {
110                format = (String)opts.get("imageio.input.image.toolkit.opts.format");
111                method = "Toolkit";
112            } else if (name.equals("imageio.input.image.toolkit.tests.gdkLoadImage")) {
113                format = (String)opts.get("imageio.input.image.toolkit.opts.format");
114                method = "GdkPixBuf";
115            } else if (name.equals("imageio.input.image.jpegcodec.tests.decodeAsBufferedImage")) {
116                format = "jpg";
117                method = "JPEGCodec";
118            } else {
119                System.err.println("skipping unrecognized key: " + name);
120                continue;
121            }
122
123            //System.out.println(format + ": " + method + " = " + score);
124            Hashtable fmtResults = (Hashtable)allResults.get(format);
125            if (fmtResults == null) {
126                fmtResults = new Hashtable();
127                allResults.put(format, fmtResults);
128            }
129            Hashtable testResults = (Hashtable)fmtResults.get(testname);
130            if (testResults == null) {
131                testResults = new Hashtable();
132                fmtResults.put(testname, testResults);
133            }
134            testResults.put(method, new Double(score));
135        }
136
137        if (wikiStyle) {
138            printWikiTable();
139        } else {
140            printHtmlTable();
141        }
142    }
143
144    private static void printWikiTable() {
145        // print a table for each format
146        Enumeration allKeys = allResults.keys();
147        while (allKeys.hasMoreElements()) {
148            String format = (String)allKeys.nextElement();
149            System.out.println("---+++ " + format.toUpperCase());
150
151            Hashtable fmtResults = (Hashtable)allResults.get(format);
152            Enumeration testKeys = fmtResults.keys();
153            String[] tests = toSortedArray(testKeys, true);
154
155            // print the column headers
156            Hashtable testResults = (Hashtable)fmtResults.get(tests[0]);
157            String[] methods = new String[testResults.keySet().size()];
158            for (int k = 0, i = 0; i < methodKeys.length; i++) {
159                if (testResults.containsKey(methodKeys[i])) {
160                    methods[k++] = methodKeys[i];
161                }
162            }
163            System.out.print("| |");
164            for (int i = 0; i < methods.length; i++) {
165                System.out.print(" *" + methods[i] + "* |");
166                if (i > 0) {
167                    System.out.print(" *%* |");
168                }
169            }
170            System.out.println("");
171
172            // print all rows in the table
173            for (int i = 0; i < tests.length; i++) {
174                String testname = tests[i];
175                testResults = (Hashtable)fmtResults.get(testname);
176                System.out.print("| " + testname + " |");
177                double baseres = 0.0;
178                for (int j = 0; j < methods.length; j++) {
179                    Double result = (Double)testResults.get(methods[j]);
180                    double res = result.doubleValue();
181
182                    System.out.print("   " +
183                                     decimalFormat.format(res) +
184                                     " | ");
185
186                    if (j == 0) {
187                        baseres = res;
188                    } else {
189                        double diff = ((res - baseres) / baseres) * 100.0;
190                        System.out.print("   "+
191                                         decimalFormat.format(diff) +
192                                         " |");
193                    }
194                }
195                System.out.println("");
196            }
197            System.out.println("");
198        }
199    }
200
201    private static void printHtmlTable() {
202        System.out.println("<html><body>\n");
203
204        // print a table for each format
205        Enumeration allKeys = allResults.keys();
206        while (allKeys.hasMoreElements()) {
207            String format = (String)allKeys.nextElement();
208            System.out.println("<h3>" + format.toUpperCase() + "</h3>");
209            System.out.println("<table border=\"1\">");
210
211            Hashtable fmtResults = (Hashtable)allResults.get(format);
212            Enumeration testKeys = fmtResults.keys();
213            String[] tests = toSortedArray(testKeys, true);
214
215            // print the column headers
216            Hashtable testResults = (Hashtable)fmtResults.get(tests[0]);
217            String[] methods = new String[testResults.keySet().size()];
218            for (int k = 0, i = 0; i < methodKeys.length; i++) {
219                if (testResults.containsKey(methodKeys[i])) {
220                    methods[k++] = methodKeys[i];
221                }
222            }
223            System.out.print("<tr><td></td>");
224            for (int i = 0; i < methods.length; i++) {
225                printHtmlCell("<b>"+methods[i]+"</b>", "#99CCCC", "center");
226                if (i > 0) {
227                    printHtmlCell("<b>%</b>", "#99CCCC", "center");
228                }
229            }
230            System.out.println("</tr>");
231
232            // print all rows in the table
233            for (int i = 0; i < tests.length; i++) {
234                String rowcolor = (i % 2 == 0) ? "#FFFFCC" : "#FFFFFF";
235                String testname = tests[i];
236                testResults = (Hashtable)fmtResults.get(testname);
237                System.out.print("<tr>");
238                printHtmlCell(testname, rowcolor, "left");
239                double baseres = 0.0;
240                for (int j = 0; j < methods.length; j++) {
241                    Double result = (Double)testResults.get(methods[j]);
242                    double res = result.doubleValue();
243
244                    printHtmlCell(decimalFormat.format(res),
245                                  rowcolor, "right");
246
247                    if (j == 0) {
248                        baseres = res;
249                    } else {
250                        double diff = ((res - baseres) / baseres) * 100.0;
251                        String cellcolor;
252                        if (Math.abs(diff) <= 5.0) {
253                            cellcolor = "#CFCFFF";
254                        } else if (diff < -5.0) {
255                            cellcolor = "#CFFFCF";
256                        } else {
257                            cellcolor = "#FFCFCF";
258                        }
259                        String difftext = decimalFormat.format(diff);
260                        if (diff > 0.0) {
261                            difftext = "+" + difftext;
262                        }
263                        printHtmlCell(difftext, cellcolor, "right");
264                        System.out.println("");
265                    }
266                }
267                System.out.println("</tr>");
268            }
269            System.out.println("</table><br>\n");
270        }
271
272        System.out.println("</body></html>");
273    }
274
275    private static void printHtmlCell(String s, String color, String align) {
276        System.out.print("<td bgcolor=\"" + color +
277                         "\" align=\"" + align + "\">" + s +
278                         "</td>");
279    }
280
281    private static String[] toSortedArray(Enumeration e, boolean special) {
282        Vector keylist = new Vector();
283        while (e.hasMoreElements()) {
284            String key = (String)e.nextElement();
285            keylist.add(key);
286        }
287        String keys[] = new String[keylist.size()];
288        keylist.copyInto(keys);
289        if (special) {
290            sort2(keys);
291        } else {
292            sort(keys);
293        }
294        return keys;
295    }
296
297    public static void sort(String strs[]) {
298        for (int i = 1; i < strs.length; i++) {
299            for (int j = i; j > 0; j--) {
300                if (strs[j].compareTo(strs[j-1]) >= 0) {
301                    break;
302                }
303                String tmp = strs[j-1];
304                strs[j-1] = strs[j];
305                strs[j] = tmp;
306            }
307        }
308    }
309
310    public static void sort2(String strs[]) {
311        for (int i = 1; i < strs.length; i++) {
312            for (int j = i; j > 0; j--) {
313                if (compare(strs[j-1], strs[j])) {
314                    break;
315                }
316                String tmp = strs[j-1];
317                strs[j-1] = strs[j];
318                strs[j] = tmp;
319            }
320        }
321    }
322
323    private static int magic(String s) {
324        if (s.endsWith("random")) {
325            return 3;
326        } else if (s.endsWith("photo")) {
327            return 2;
328        } else if (s.endsWith("vector")) {
329            return 1;
330        } else {
331            return 0;
332        }
333    }
334
335    private static boolean compare(String s1, String s2) {
336        String sizestr1 = s1.substring(s1.indexOf('=')+1, s1.indexOf(','));
337        String sizestr2 = s2.substring(s2.indexOf('=')+1, s2.indexOf(','));
338        int size1 = Integer.parseInt(sizestr1);
339        int size2 = Integer.parseInt(sizestr2);
340        if (size1 == size2) {
341            return (magic(s1) < magic(s2));
342        } else {
343            return (size1 < size2);
344        }
345    }
346
347    private static void printUsage() {
348        System.out.println("java -cp J2DAnalyzer.jar " +
349                           IIOComparator.class.getName() +
350                           " [-wiki] <resultfile>");
351    }
352
353    public static void main(String[] args) {
354        if (args.length == 2) {
355            if (args[0].equals("-wiki")) {
356                wikiStyle = true;
357                printIIOTable(args[1]);
358            } else {
359                printUsage();
360            }
361        } else if (args.length == 1) {
362            printIIOTable(args[0]);
363        } else {
364            printUsage();
365        }
366    }
367}
368