Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 ''' | 1 ''' |
| 2 Created on May 16, 2011 | 2 Created on May 16, 2011 |
| 3 | 3 |
| 4 @author: bungeman | 4 @author: bungeman |
| 5 ''' | 5 ''' |
| 6 import bench_util | 6 import bench_util |
| 7 import getopt | 7 import getopt |
| 8 import httplib | 8 import httplib |
| 9 import itertools | 9 import itertools |
| 10 import json | 10 import json |
| 11 import os | 11 import os |
| 12 import re | 12 import re |
| 13 import sys | 13 import sys |
| 14 import urllib | 14 import urllib |
| 15 import urllib2 | 15 import urllib2 |
| 16 import xml.sax.saxutils | 16 import xml.sax.saxutils |
| 17 | 17 |
| 18 # Maximum expected number of characters we expect in an svn revision. | 18 # Maximum expected number of characters we expect in an svn revision. |
| 19 MAX_SVN_REV_LENGTH = 5 | 19 MAX_SVN_REV_LENGTH = 5 |
| 20 | 20 |
| 21 # Indices for getting elements from bench expectation files. | |
| 22 # See bench_expectations_<builder>.txt for details. | |
| 23 EXPECTED_IDX = -3 | |
| 24 LB_IDX = -2 | |
| 25 UB_IDX = -1 | |
| 26 | |
| 21 def usage(): | 27 def usage(): |
| 22 """Prints simple usage information.""" | 28 """Prints simple usage information.""" |
| 23 | 29 |
| 24 print '-a <representation_alg> bench representation algorithm to use. ' | 30 print '-a <representation_alg> bench representation algorithm to use. ' |
| 25 print ' Defaults to "25th". See bench_util.py for details.' | 31 print ' Defaults to "25th". See bench_util.py for details.' |
| 26 print '-b <builder> name of the builder whose bench data we are checking.' | 32 print '-b <builder> name of the builder whose bench data we are checking.' |
| 27 print '-d <dir> a directory containing bench_<revision>_<scalar> files.' | 33 print '-d <dir> a directory containing bench_<revision>_<scalar> files.' |
| 28 print '-e <file> file containing expected bench builder values/ranges.' | 34 print '-e <file> file containing expected bench builder values/ranges.' |
| 29 print ' Will raise exception if actual bench values are out of range.' | 35 print ' Will raise exception if actual bench values are out of range.' |
| 30 print ' See bench_expectations_<builder>.txt for data format / examples.' | 36 print ' See bench_expectations_<builder>.txt for data format / examples.' |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 elements = expectation.strip().split(',') | 133 elements = expectation.strip().split(',') |
| 128 if not elements[0] or elements[0].startswith('#'): | 134 if not elements[0] or elements[0].startswith('#'): |
| 129 continue | 135 continue |
| 130 if len(elements) != 5: | 136 if len(elements) != 5: |
| 131 raise Exception("Invalid expectation line format: %s" % | 137 raise Exception("Invalid expectation line format: %s" % |
| 132 expectation) | 138 expectation) |
| 133 bench_entry = elements[0] + ',' + elements[1] | 139 bench_entry = elements[0] + ',' + elements[1] |
| 134 if bench_entry in expectations: | 140 if bench_entry in expectations: |
| 135 raise Exception("Dup entries for bench expectation %s" % | 141 raise Exception("Dup entries for bench expectation %s" % |
| 136 bench_entry) | 142 bench_entry) |
| 137 # [<Bench_BmpConfig_TimeType>,<Platform-Alg>] -> (LB, UB) | 143 # [<Bench_BmpConfig_TimeType>,<Platform-Alg>] -> (LB, UB, EXPECTED) |
| 138 expectations[bench_entry] = (float(elements[-2]), | 144 expectations[bench_entry] = (float(elements[LB_IDX]), |
| 139 float(elements[-1])) | 145 float(elements[UB_IDX]), |
| 146 float(elements[EXPECTED_IDX])) | |
| 140 | 147 |
| 141 def check_expectations(lines, expectations, revision, key_suffix): | 148 def check_expectations(lines, expectations, key_suffix): |
| 142 """Check if there are benches in the given revising out of range. | 149 """Check if there are benches in the given revising out of range. |
|
epoger
2014/02/19 21:27:51
revising -> revision ?
Actually, revision disappe
benchen
2014/02/19 21:47:54
Done.
| |
| 150 | |
| 151 For each input line in lines, checks the expectations dictionary to see if | |
| 152 the bench is out of the given range. | |
| 153 | |
| 154 Args: | |
| 155 lines: dictionary mapping Label objects to the bench values. | |
| 156 expectations: dictionary returned by read_expectations(). | |
| 157 key_suffix: string of <Platform>-<Alg> containing the bot platform and the | |
| 158 bench representation algorithm (default to "25th"). | |
|
epoger
2014/02/19 21:27:51
I don't see anything about defaulting to "25th" in
benchen
2014/02/19 21:47:54
Agreed. Done.
On 2014/02/19 21:27:51, epoger wrote
| |
| 159 | |
| 160 Returns: | |
| 161 No return value. | |
| 162 | |
| 163 Raises: | |
| 164 Exception containing bench data that are out of range, if nonempty. | |
|
epoger
2014/02/19 21:27:51
nonempty -> any
benchen
2014/02/19 21:47:54
Done.
| |
| 143 """ | 165 """ |
| 144 # The platform for this bot, to pass to the dashboard plot. | 166 # The platform for this bot, to pass to the dashboard plot. |
| 145 platform = key_suffix[ : key_suffix.rfind('-')] | 167 platform = key_suffix[ : key_suffix.rfind('-')] |
| 146 exceptions = [] | 168 # Tuple of dictionaries recording exceptions that are slower and faster, |
| 169 # respectively. Each dictionary maps off_ratio (ratio of actual to expected) | |
| 170 # to a list of correspondig exception messages. | |
|
epoger
2014/02/19 21:27:51
correspondig -> corresponding
benchen
2014/02/19 21:47:54
Done. How did you catch this one?
On 2014/02/19 21
| |
| 171 exceptions = ({}, {}) | |
| 147 for line in lines: | 172 for line in lines: |
| 148 line_str = str(line) | 173 line_str = str(line) |
| 149 line_str = line_str[ : line_str.find('_{')] | 174 line_str = line_str[ : line_str.find('_{')] |
| 150 bench_platform_key = line_str + ',' + key_suffix | 175 bench_platform_key = line_str + ',' + key_suffix |
| 151 if bench_platform_key not in expectations: | 176 if bench_platform_key not in expectations: |
| 152 continue | 177 continue |
| 153 this_bench_value = lines[line] | 178 this_bench_value = lines[line] |
| 154 this_min, this_max = expectations[bench_platform_key] | 179 this_min, this_max, this_expected = expectations[bench_platform_key] |
| 155 if this_bench_value < this_min or this_bench_value > this_max: | 180 if this_bench_value < this_min or this_bench_value > this_max: |
| 156 exception = 'Bench %s value %s out of range [%s, %s].' % ( | 181 off_ratio = this_bench_value / this_expected |
| 157 bench_platform_key, this_bench_value, this_min, this_max) | 182 exception = 'Bench %s out of range [%s, %s] (%s vs %s, %s%%).' % ( |
| 158 exceptions.append(exception) | 183 bench_platform_key, this_min, this_max, this_bench_value, |
| 159 if exceptions: | 184 this_expected, (off_ratio - 1) * 100) |
| 160 raise Exception('Bench values out of range:\n' + | 185 if off_ratio > 1: # Bench is slower. |
| 161 '\n'.join(exceptions)) | 186 exceptions[0].setdefault(off_ratio, []).append(exception) |
|
epoger
2014/02/19 21:27:51
Rather than magic values 0 and 1, please use defin
benchen
2014/02/19 21:47:54
Done using constants.
On 2014/02/19 21:27:51, epog
| |
| 187 else: | |
| 188 exceptions[1].setdefault(off_ratio, []).append(exception) | |
| 189 outputs = [] | |
| 190 for i in [0, 1]: | |
| 191 if exceptions[i]: | |
| 192 ratios = exceptions[i].keys() | |
| 193 ratios.sort(reverse=True) | |
| 194 li = [] | |
| 195 for ratio in ratios: | |
| 196 li.extend(exceptions[i][ratio]) | |
| 197 header = '%s Slower benche(s) (Sorted):' % len(li) | |
|
epoger
2014/02/19 21:27:51
I think this would be clearer:
'%s benches got sl
benchen
2014/02/19 21:47:54
Agreed. Done.
On 2014/02/19 21:27:51, epoger wrote
| |
| 198 if i == 1: | |
| 199 header = header.replace('Slower', 'Faster') | |
| 200 outputs.extend(['', header] + li) | |
| 201 | |
| 202 if outputs: | |
| 203 raise Exception('\n'.join(outputs)) | |
| 162 | 204 |
| 163 def main(): | 205 def main(): |
| 164 """Parses command line and checks bench expectations.""" | 206 """Parses command line and checks bench expectations.""" |
| 165 try: | 207 try: |
| 166 opts, _ = getopt.getopt(sys.argv[1:], | 208 opts, _ = getopt.getopt(sys.argv[1:], |
| 167 "a:b:d:e:r:", | 209 "a:b:d:e:r:", |
| 168 "default-setting=") | 210 "default-setting=") |
| 169 except getopt.GetoptError, err: | 211 except getopt.GetoptError, err: |
| 170 print str(err) | 212 print str(err) |
| 171 usage() | 213 usage() |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 203 platform_and_alg = bot + '-' + rep | 245 platform_and_alg = bot + '-' + rep |
| 204 | 246 |
| 205 data_points = parse_dir(directory, | 247 data_points = parse_dir(directory, |
| 206 {}, # Sets default settings to empty. | 248 {}, # Sets default settings to empty. |
| 207 rev, | 249 rev, |
| 208 rep) | 250 rep) |
| 209 | 251 |
| 210 bench_dict = create_bench_dict(data_points) | 252 bench_dict = create_bench_dict(data_points) |
| 211 | 253 |
| 212 if bench_expectations: | 254 if bench_expectations: |
| 213 check_expectations(bench_dict, bench_expectations, rev, | 255 check_expectations(bench_dict, bench_expectations, platform_and_alg) |
| 214 platform_and_alg) | |
| 215 | 256 |
| 216 | 257 |
| 217 if __name__ == "__main__": | 258 if __name__ == "__main__": |
| 218 main() | 259 main() |
| OLD | NEW |