Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env dart | |
| 2 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 3 // for details. All rights reserved. Use of this source code is governed by a | |
| 4 // BSD-style license that can be found in the LICENSE file. | |
| 5 | |
| 6 /** | |
| 7 * Script that prints in a table format a comparison of two benchmark results. | |
| 8 * The input is given as two json files containing the benchmark results. | |
| 9 */ | |
|
Jennifer Messerly
2013/01/07 21:07:46
library test.perf.compare; ?
Siggi Cherem (dart-lang)
2013/01/08 02:26:18
Done.
| |
| 10 | |
| 11 import 'dart:io'; | |
| 12 import 'dart:json'; | |
| 13 import 'dart:math' as math; | |
| 14 | |
| 15 main() { | |
| 16 var args = new Options().arguments; | |
| 17 if (args.length < 2) { | |
| 18 print('usage: compare.dart results1.json results2.json [filter]'); | |
| 19 exit(1); | |
| 20 } | |
| 21 | |
| 22 var path1 = args[0]; | |
| 23 var path2 = args[1]; | |
| 24 var file1 = new File(path1).readAsStringSync(); | |
| 25 var file2 = new File(path2).readAsStringSync(); | |
| 26 var filter = args.length > 2 ? new RegExp(args[2]) : null; | |
| 27 | |
| 28 var results = []; | |
| 29 var map1 = JSON.parse(file1); | |
| 30 var map2 = JSON.parse(file2); | |
| 31 | |
| 32 for (var key in map1.keys) { | |
| 33 if (map2.containsKey(key)) { | |
| 34 results.add(new _ResultPair(key, map1[key], map2[key])); | |
| 35 } else { | |
| 36 results.add(new _ResultPair(key, map1[key], null)); | |
| 37 } | |
| 38 } | |
| 39 | |
| 40 for (var key in map2.keys) { | |
| 41 if (!map1.containsKey(key)) { | |
| 42 results.add(new _ResultPair(key, null, map2[key])); | |
| 43 } | |
| 44 } | |
| 45 | |
| 46 print('Comparing:\n (a) $path1\n (b) $path2'); | |
| 47 _printLine('Benchmark', '(a)', '(b)', '% (b - a)/a'); | |
| 48 _printLine('------------------------------', '--------------', | |
| 49 '--------------', '--------------'); | |
| 50 var scores1 = []; | |
| 51 var scores2 = []; | |
| 52 var someNull = false; | |
| 53 if (filter != null) { | |
| 54 results = results.filter((s) => filter.hasMatch(s.name)); | |
| 55 } | |
| 56 results.sort((a, b) { | |
| 57 if (a.name.startsWith('dart') && b.name.startsWith('js ')) return 1; | |
|
Jennifer Messerly
2013/01/07 21:07:46
since ResultPair is its own class, perhaps make it
Siggi Cherem (dart-lang)
2013/01/08 02:26:18
Done.
| |
| 58 if (a.name.startsWith('js ') && b.name.startsWith('dart')) return -1; | |
| 59 if (a.factor != null && b.factor != null) { | |
| 60 var res = a.factor.compareTo(b.factor); | |
| 61 if (res != 0) return res; | |
| 62 } | |
| 63 return a.name.compareTo(b.name); | |
| 64 }); | |
| 65 | |
| 66 for (var entry in results) { | |
| 67 print(entry); | |
| 68 if (entry.score1 != null) { | |
| 69 scores1.add(entry.time1); | |
| 70 } else { | |
| 71 someNull = true; | |
| 72 } | |
| 73 if (entry.score2 != null) { | |
| 74 scores2.add(entry.time2); | |
| 75 } else { | |
| 76 someNull = true; | |
| 77 } | |
| 78 | |
| 79 } | |
| 80 _printLine('------------------------------', '--------------', | |
| 81 '--------------', '--------------'); | |
| 82 print(new _ResultPair('Geometric mean', _geomean(scores1), | |
| 83 _geomean(scores2))); | |
| 84 | |
| 85 if (someNull) { | |
| 86 scores1 = []; | |
| 87 scores2 = []; | |
| 88 for (var entry in results) { | |
| 89 if (entry.score1 != null && entry.score2 != null) { | |
| 90 scores1.add(entry.score1); | |
| 91 scores2.add(entry.score2); | |
| 92 } | |
| 93 } | |
| 94 print(new _ResultPair('Geometric mean (both avail)', | |
| 95 _geomean(scores1), _geomean(scores2))); | |
| 96 } | |
| 97 } | |
| 98 | |
| 99 class _ResultPair { | |
|
Jennifer Messerly
2013/01/07 21:07:46
general note: I don't think most of these classes
Siggi Cherem (dart-lang)
2013/01/08 02:26:18
Done.
| |
| 100 final String name; | |
| 101 final num time1; | |
| 102 final num time2; | |
| 103 final num score1; | |
| 104 final num score2; | |
| 105 | |
| 106 num get factor => score1 == null || score2 == null ? null | |
| 107 : ((score2 - score1) * 100.0) / score1; | |
| 108 | |
| 109 _ResultPair(this.name, double time1, double time2) | |
| 110 : this.time1 = time1, this.time2 = time2, | |
| 111 score1 = time1 == null ? null : 1000000.0 / time1, | |
| 112 score2 = time2 == null ? null : 1000000.0 / time2; | |
| 113 | |
| 114 String toString() { | |
| 115 var buff = new StringBuffer(); | |
| 116 buff.add(name); | |
| 117 _ensure(buff, 30); | |
| 118 _addNumber(buff, score1, 45); | |
| 119 _addNumber(buff, score2, 60); | |
| 120 _addNumber(buff, factor, 75, color: true); | |
| 121 return buff.toString(); | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 _printLine(String col0, String col1, String col2, String col3) { | |
| 126 var buff = new StringBuffer(); | |
| 127 buff.add(col0); | |
| 128 _ensure(buff, 30); | |
| 129 _padRight(buff, col1, 45); | |
| 130 _padRight(buff, col2, 60); | |
| 131 _padRight(buff, col3, 75); | |
| 132 print(buff.toString()); | |
| 133 } | |
| 134 | |
| 135 _ensure(StringBuffer buff, int ensure) { | |
|
Jennifer Messerly
2013/01/07 21:07:46
I wonder if something like _padSpaces or _ensureCo
Siggi Cherem (dart-lang)
2013/01/08 02:26:18
Done.
| |
| 136 while (buff.length < ensure) { | |
| 137 buff.add(' '); | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 _addNumber(StringBuffer buff, num value, int ensure, {bool color: false}) { | |
| 142 var str; | |
| 143 if (value == null) { | |
| 144 str = '--'; | |
| 145 } else { | |
| 146 str = (value > 100) ? value.toStringAsFixed(0) : value.toStringAsFixed(2); | |
|
Jennifer Messerly
2013/01/07 21:07:46
If value is between 10 and 100 should it use toStr
Siggi Cherem (dart-lang)
2013/01/08 02:26:18
Done.
| |
| 147 } | |
| 148 while (buff.length + str.length < ensure) { | |
| 149 buff.add(' '); | |
| 150 } | |
| 151 if (color) _addColor(buff, value); | |
| 152 buff.add(str); | |
| 153 if (color) _removeColor(buff, value); | |
| 154 } | |
| 155 | |
| 156 _addColor(StringBuffer buff, num value) { | |
| 157 if (value == null || value.abs() < 2) return; | |
| 158 var color; | |
| 159 if (value >= 2 && value < 7) { | |
| 160 color = '[32m'; | |
| 161 } else if (value >= 7) { | |
| 162 color = '[32;1m'; | |
| 163 } else if (value <= -2 && value > -7) { | |
| 164 color = '[38;5;208m'; | |
| 165 } else if (value <= -7) { | |
| 166 color = '[31;1m'; | |
| 167 } | |
| 168 buff.add(color); | |
| 169 } | |
| 170 | |
| 171 _removeColor(StringBuffer buff, num value) { | |
| 172 if (value == null || value.abs() < 2) return; | |
| 173 buff.add('[0m'); | |
| 174 } | |
| 175 | |
| 176 _padRight(StringBuffer buff, String str, int ensure) { | |
| 177 while (buff.length + str.length < ensure) { | |
| 178 buff.add(' '); | |
| 179 } | |
| 180 buff.add(str); | |
| 181 } | |
| 182 | |
| 183 _geomean(List<num> numbers) { | |
| 184 var log = 0.0; | |
| 185 for (var n in numbers) { | |
| 186 log += math.log(n); | |
| 187 } | |
| 188 return math.pow(math.E, log / numbers.length); | |
| 189 } | |
| OLD | NEW |