OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Performance Test Bisect Tool | 6 """Performance Test Bisect Tool |
7 | 7 |
8 This script bisects a series of changelists using binary search. It starts at | 8 This script bisects a series of changelists using binary search. It starts at |
9 a bad revision where a performance metric has regressed, and asks for a last | 9 a bad revision where a performance metric has regressed, and asks for a last |
10 known-good revision. It will then binary search across this revision range by | 10 known-good revision. It will then binary search across this revision range by |
(...skipping 2219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2230 next_revision_data['passed'] = 'Build Failed' | 2230 next_revision_data['passed'] = 'Build Failed' |
2231 | 2231 |
2232 print run_results[0] | 2232 print run_results[0] |
2233 | 2233 |
2234 # If the build is broken, remove it and redo search. | 2234 # If the build is broken, remove it and redo search. |
2235 revision_list.pop(next_revision_index) | 2235 revision_list.pop(next_revision_index) |
2236 | 2236 |
2237 max_revision -= 1 | 2237 max_revision -= 1 |
2238 | 2238 |
2239 if self.opts.output_buildbot_annotations: | 2239 if self.opts.output_buildbot_annotations: |
| 2240 self._PrintPartialResults(results) |
2240 bisect_utils.OutputAnnotationStepClosed() | 2241 bisect_utils.OutputAnnotationStepClosed() |
2241 else: | 2242 else: |
2242 # Weren't able to sync and retrieve the revision range. | 2243 # Weren't able to sync and retrieve the revision range. |
2243 results['error'] = 'An error occurred attempting to retrieve revision '\ | 2244 results['error'] = 'An error occurred attempting to retrieve revision '\ |
2244 'range: [%s..%s]' % (good_revision, bad_revision) | 2245 'range: [%s..%s]' % (good_revision, bad_revision) |
2245 | 2246 |
2246 return results | 2247 return results |
2247 | 2248 |
| 2249 def _PrintPartialResults(self, results_dict): |
| 2250 revision_data = results_dict['revision_data'] |
| 2251 revision_data_sorted = sorted(revision_data.iteritems(), |
| 2252 key = lambda x: x[1]['sort']) |
| 2253 results_dict = self._GetResultsDict(revision_data, revision_data_sorted) |
| 2254 first_working_revision = results_dict['first_working_revision'] |
| 2255 last_broken_revision = results_dict['last_broken_revision'] |
| 2256 |
| 2257 self._PrintTestedCommitsTable(revision_data_sorted, |
| 2258 results_dict['first_working_revision'], |
| 2259 results_dict['last_broken_revision'], |
| 2260 100, final_step=False) |
| 2261 |
2248 def _PrintConfidence(self, results_dict): | 2262 def _PrintConfidence(self, results_dict): |
2249 # The perf dashboard specifically looks for the string | 2263 # The perf dashboard specifically looks for the string |
2250 # "Confidence in Bisection Results: 100%" to decide whether or not | 2264 # "Confidence in Bisection Results: 100%" to decide whether or not |
2251 # to cc the author(s). If you change this, please update the perf | 2265 # to cc the author(s). If you change this, please update the perf |
2252 # dashboard as well. | 2266 # dashboard as well. |
2253 print 'Confidence in Bisection Results: %d%%' % results_dict['confidence'] | 2267 print 'Confidence in Bisection Results: %d%%' % results_dict['confidence'] |
2254 | 2268 |
2255 def _PrintBanner(self, results_dict): | 2269 def _PrintBanner(self, results_dict): |
2256 print | 2270 print |
2257 print " __o_\___ Aw Snap! We hit a speed bump!" | 2271 print " __o_\___ Aw Snap! We hit a speed bump!" |
(...skipping 30 matching lines...) Expand all Loading... |
2288 except IndexError: | 2302 except IndexError: |
2289 print | 2303 print |
2290 print 'Failed to parse svn revision from body:' | 2304 print 'Failed to parse svn revision from body:' |
2291 print | 2305 print |
2292 print info['body'] | 2306 print info['body'] |
2293 print | 2307 print |
2294 print 'Commit : %s' % cl | 2308 print 'Commit : %s' % cl |
2295 print 'Date : %s' % info['date'] | 2309 print 'Date : %s' % info['date'] |
2296 | 2310 |
2297 def _PrintTestedCommitsTable(self, revision_data_sorted, | 2311 def _PrintTestedCommitsTable(self, revision_data_sorted, |
2298 first_working_revision, last_broken_revision, confidence): | 2312 first_working_revision, last_broken_revision, confidence, |
| 2313 final_step=True): |
2299 print | 2314 print |
2300 print 'Tested commits:' | 2315 if final_step: |
| 2316 print 'Tested commits:' |
| 2317 else: |
| 2318 print 'Partial results:' |
2301 print ' %20s %40s %12s %14s %13s' % ('Depot'.center(20, ' '), | 2319 print ' %20s %40s %12s %14s %13s' % ('Depot'.center(20, ' '), |
2302 'Commit SHA'.center(40, ' '), 'Mean'.center(12, ' '), | 2320 'Commit SHA'.center(40, ' '), 'Mean'.center(12, ' '), |
2303 'Std. Error'.center(14, ' '), 'State'.center(13, ' ')) | 2321 'Std. Error'.center(14, ' '), 'State'.center(13, ' ')) |
2304 state = 0 | 2322 state = 0 |
2305 for current_id, current_data in revision_data_sorted: | 2323 for current_id, current_data in revision_data_sorted: |
2306 if current_data['value']: | 2324 if current_data['value']: |
2307 if (current_id == last_broken_revision or | 2325 if (current_id == last_broken_revision or |
2308 current_id == first_working_revision): | 2326 current_id == first_working_revision): |
2309 # If confidence is too low, don't add this empty line since it's | 2327 # If confidence is too low, don't add this empty line since it's |
2310 # used to put focus on a suspected CL. | 2328 # used to put focus on a suspected CL. |
2311 if confidence: | 2329 if confidence and final_step: |
2312 print | 2330 print |
2313 state += 1 | 2331 state += 1 |
| 2332 if state == 2 and not final_step: |
| 2333 # Just want a separation between "bad" and "good" cl's. |
| 2334 print |
2314 | 2335 |
2315 state_str = 'Bad' | 2336 state_str = 'Bad' |
2316 if state == 1: | 2337 if state == 1 and final_step: |
2317 state_str = 'Suspected CL' | 2338 state_str = 'Suspected CL' |
2318 elif state == 2: | 2339 elif state == 2: |
2319 state_str = 'Good' | 2340 state_str = 'Good' |
2320 | 2341 |
2321 # If confidence is too low, don't bother outputting good/bad. | 2342 # If confidence is too low, don't bother outputting good/bad. |
2322 if not confidence: | 2343 if not confidence: |
2323 state_str = '' | 2344 state_str = '' |
2324 state_str = state_str.center(13, ' ') | 2345 state_str = state_str.center(13, ' ') |
2325 | 2346 |
2326 std_error = ('+-%.02f' % | 2347 std_error = ('+-%.02f' % |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2374 print 'Average build time : %s' % datetime.timedelta( | 2395 print 'Average build time : %s' % datetime.timedelta( |
2375 seconds=int(step_build_time_avg)) | 2396 seconds=int(step_build_time_avg)) |
2376 print 'Average test time : %s' % datetime.timedelta( | 2397 print 'Average test time : %s' % datetime.timedelta( |
2377 seconds=int(step_perf_time_avg)) | 2398 seconds=int(step_perf_time_avg)) |
2378 | 2399 |
2379 def _PrintWarnings(self): | 2400 def _PrintWarnings(self): |
2380 if not self.warnings: | 2401 if not self.warnings: |
2381 return | 2402 return |
2382 print | 2403 print |
2383 print 'WARNINGS:' | 2404 print 'WARNINGS:' |
2384 for w in self.warnings: | 2405 for w in set(self.warnings): |
2385 print ' !!! %s' % w | 2406 print ' !!! %s' % w |
2386 | 2407 |
2387 def _GetResultsDict(self, revision_data, revision_data_sorted): | 2408 def _GetResultsDict(self, revision_data, revision_data_sorted): |
2388 # Find range where it possibly broke. | 2409 # Find range where it possibly broke. |
2389 first_working_revision = None | 2410 first_working_revision = None |
2390 first_working_revision_index = -1 | 2411 first_working_revision_index = -1 |
2391 last_broken_revision = None | 2412 last_broken_revision = None |
2392 last_broken_revision_index = -1 | 2413 last_broken_revision_index = -1 |
2393 | 2414 |
2394 for i in xrange(len(revision_data_sorted)): | 2415 for i in xrange(len(revision_data_sorted)): |
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2966 # The perf dashboard scrapes the "results" step in order to comment on | 2987 # The perf dashboard scrapes the "results" step in order to comment on |
2967 # bugs. If you change this, please update the perf dashboard as well. | 2988 # bugs. If you change this, please update the perf dashboard as well. |
2968 bisect_utils.OutputAnnotationStepStart('Results') | 2989 bisect_utils.OutputAnnotationStepStart('Results') |
2969 print 'Error: %s' % e.message | 2990 print 'Error: %s' % e.message |
2970 if opts.output_buildbot_annotations: | 2991 if opts.output_buildbot_annotations: |
2971 bisect_utils.OutputAnnotationStepClosed() | 2992 bisect_utils.OutputAnnotationStepClosed() |
2972 return 1 | 2993 return 1 |
2973 | 2994 |
2974 if __name__ == '__main__': | 2995 if __name__ == '__main__': |
2975 sys.exit(main()) | 2996 sys.exit(main()) |
OLD | NEW |