1 /* 2 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 Used by DemoSupport.gmk: 26 27 - calculate the geomean and stdev of benchmark runs 28 - write markdown snippets for rendering benchmark results as a chart on GitHub .MD files 29 30 Example: 31 32 helidon-quickstart-se$ tbjava ../lib/GithubMDChart.java < mainline_vs_premain.csv 33 run,mainline default,mainline custom static CDS,premain custom static CDS only,premain AOT new workflow 34 1,398,240,175,116 35 2,380,239,138,110 36 3,411,287,144,113 37 4,399,246,147,112 38 5,402,245,147,110 39 6,398,242,142,122 40 7,383,242,146,111 41 8,388,260,152,108 42 9,395,250,149,113 43 10,380,241,143,132 44 Geomean,393.28,248.84,148.01,114.51 45 Stdev,9.78,13.91,9.63,6.86 46 47 ```mermaid 48 gantt 49 title Elapsed time (ms) 50 todayMarker off 51 dateFormat X 52 axisFormat %s 53 54 mainline default : 0, 393.28 55 mainline custom static CDS : 0, 248.84 56 premain custom static CDS only : 0, 148.01 57 premain AOT new workflow : 0, 114.51 58 ``` 59 60 */ 61 62 import java.io.PrintWriter; 63 import java.util.Scanner; 64 import java.util.ArrayList; 65 66 public class GithubMDChart { 67 @SuppressWarnings("unchecked") 68 public static void main(String args[]) throws Exception { 69 Scanner input = new Scanner(System.in); 70 String line = input.nextLine(); 71 //System.out.println(line); 72 String head[] = line.split(","); 73 Object[] groups = new Object[head.length]; 74 String[] geomeans = new String[head.length]; 75 for (int i = 0; i < head.length; i++) { 76 groups[i] = new ArrayList<Double>(); 77 } 78 while (input.hasNext()) { 79 line = input.nextLine(); 80 //System.out.println(line); 81 String parts[] = line.split(","); 82 for (int i = 0; i < head.length; i++) { 83 ArrayList<Double> list = (ArrayList<Double>)(groups[i]); 84 list.add(Double.valueOf(Double.parseDouble(parts[i]))); 85 } 86 } 87 88 for (int i = 0; i < head.length; i++) { 89 ArrayList<Double> list = (ArrayList<Double>)(groups[i]); 90 if (i == 0) { 91 System.out.print("Geomean"); 92 } else { 93 System.out.print(","); 94 geomeans[i] = geomean(list); 95 System.out.print(geomeans[i]); 96 } 97 } 98 99 System.out.println(); 100 101 for (int i = 0; i < head.length; i++) { 102 ArrayList<Double> list = (ArrayList<Double>)(groups[i]); 103 if (i == 0) { 104 System.out.print("Stdev"); 105 } else { 106 System.out.print(","); 107 System.out.print(stdev(list)); 108 } 109 } 110 System.out.println(); 111 System.out.println("Markdown snippets in " + args[0]); 112 113 PrintWriter pw = new PrintWriter(args[0]); 114 pw.println("```mermaid"); 115 pw.println("gantt"); 116 pw.println(" title Elapsed time (ms, smaller is better)"); 117 pw.println(" todayMarker off"); 118 pw.println(" dateFormat X"); 119 pw.println(" axisFormat %s"); 120 pw.println(); 121 122 for (int i = 1; i < head.length; i++) { 123 pw.println(" " + head[i] + " : 0, " + geomeans[i]); 124 } 125 pw.println("```"); 126 pw.println(); 127 pw.println("-----------------Normalized---------------------------------------------"); 128 129 pw.println("```mermaid"); 130 pw.println("gantt"); 131 pw.println(" title Elapsed time (normalized, smaller is better)"); 132 pw.println(" todayMarker off"); 133 pw.println(" dateFormat X"); 134 pw.println(" axisFormat %s"); 135 pw.println(); 136 137 for (int i = 1; i < head.length; i++) { 138 double base = Double.parseDouble(geomeans[1]); 139 double me = Double.parseDouble(geomeans[i]); 140 pw.println(" " + head[i] + " : 0, " + String.format("%.0f", 1000.0 * me / base)); 141 } 142 pw.println("```"); 143 pw.close(); 144 } 145 146 147 static String geomean(ArrayList<Double> list) { 148 double log = 0.0d; 149 for (Double d : list) { 150 double v = d.doubleValue(); 151 if (v <= 0) { 152 v = 0.000001; 153 } 154 log += Math.log(v); 155 } 156 157 return String.format("%.2f", Math.exp(log / list.size())); 158 } 159 160 static String stdev(ArrayList<Double> list) { 161 double sum = 0.0; 162 for (Double d : list) { 163 sum += d.doubleValue(); 164 } 165 166 double length = list.size(); 167 double mean = sum / length; 168 169 double stdev = 0.0; 170 for (Double d : list) { 171 stdev += Math.pow(d.doubleValue() - mean, 2); 172 } 173 174 return String.format("%.2f", Math.sqrt(stdev / length)); 175 } 176 }