Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: tools/auto_bisect/bisect_perf_regression.py

Issue 645263002: Implementing direction_of_improvement (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adding missing option from command-line building logic. Improved error message. Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tools/auto_bisect/bisect_perf_regression_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 1500 matching lines...) Expand 10 before | Expand all | Expand 10 after
1511 updated_deps_content = self.UpdateDepsContents( 1511 updated_deps_content = self.UpdateDepsContents(
1512 deps_contents, depot, revision, deps_var) 1512 deps_contents, depot, revision, deps_var)
1513 # Write changes to DEPS file 1513 # Write changes to DEPS file
1514 if updated_deps_content: 1514 if updated_deps_content:
1515 WriteStringToFile(updated_deps_content, deps_file) 1515 WriteStringToFile(updated_deps_content, deps_file)
1516 return True 1516 return True
1517 except IOError, e: 1517 except IOError, e:
1518 print 'Something went wrong while updating DEPS file. [%s]' % e 1518 print 'Something went wrong while updating DEPS file. [%s]' % e
1519 return False 1519 return False
1520 1520
1521
1522 def CreateDEPSPatch(self, depot, revision): 1521 def CreateDEPSPatch(self, depot, revision):
1523 """Modifies DEPS and returns diff as text. 1522 """Modifies DEPS and returns diff as text.
1524 1523
1525 Args: 1524 Args:
1526 depot: Current depot being bisected. 1525 depot: Current depot being bisected.
1527 revision: A git hash revision of the dependency repository. 1526 revision: A git hash revision of the dependency repository.
1528 1527
1529 Returns: 1528 Returns:
1530 A tuple with git hash of chromium revision and DEPS patch text. 1529 A tuple with git hash of chromium revision and DEPS patch text.
1531 """ 1530 """
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1657 """ 1656 """
1658 success_code, failure_code = 0, -1 1657 success_code, failure_code = 0, -1
1659 1658
1660 if self.opts.debug_ignore_perf_test: 1659 if self.opts.debug_ignore_perf_test:
1661 fake_results = { 1660 fake_results = {
1662 'mean': 0.0, 1661 'mean': 0.0,
1663 'std_err': 0.0, 1662 'std_err': 0.0,
1664 'std_dev': 0.0, 1663 'std_dev': 0.0,
1665 'values': [0.0] 1664 'values': [0.0]
1666 } 1665 }
1666
1667 # When debug_fake_test_mean is set, its value is returned as the mean
1668 # and the flag is cleared so that further calls behave as if it wasn't
1669 # set (returning the fake_results dict as defined above).
1670 if self.opts.debug_fake_first_test_mean:
1671 fake_results['mean'] = float(self.opts.debug_fake_first_test_mean)
1672 self.opts.debug_fake_first_test_mean = 0
1673
1667 return (fake_results, success_code) 1674 return (fake_results, success_code)
1668 1675
1669 # For Windows platform set posix=False, to parse windows paths correctly. 1676 # For Windows platform set posix=False, to parse windows paths correctly.
1670 # On Windows, path separators '\' or '\\' are replace by '' when posix=True, 1677 # On Windows, path separators '\' or '\\' are replace by '' when posix=True,
1671 # refer to http://bugs.python.org/issue1724822. By default posix=True. 1678 # refer to http://bugs.python.org/issue1724822. By default posix=True.
1672 args = shlex.split(command_to_run, posix=not bisect_utils.IsWindowsHost()) 1679 args = shlex.split(command_to_run, posix=not bisect_utils.IsWindowsHost())
1673 1680
1674 if not _GenerateProfileIfNecessary(args): 1681 if not _GenerateProfileIfNecessary(args):
1675 err_text = 'Failed to generate profile for performance test.' 1682 err_text = 'Failed to generate profile for performance test.'
1676 return (err_text, failure_code) 1683 return (err_text, failure_code)
(...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after
2407 self.PrintRevisionsToBisectMessage(revision_list, target_depot) 2414 self.PrintRevisionsToBisectMessage(revision_list, target_depot)
2408 2415
2409 if self.opts.output_buildbot_annotations: 2416 if self.opts.output_buildbot_annotations:
2410 bisect_utils.OutputAnnotationStepStart('Gathering Reference Values') 2417 bisect_utils.OutputAnnotationStepStart('Gathering Reference Values')
2411 2418
2412 print 'Gathering reference values for bisection.' 2419 print 'Gathering reference values for bisection.'
2413 2420
2414 # Perform the performance tests on the good and bad revisions, to get 2421 # Perform the performance tests on the good and bad revisions, to get
2415 # reference values. 2422 # reference values.
2416 bad_results, good_results = self.GatherReferenceValues(good_revision, 2423 bad_results, good_results = self.GatherReferenceValues(good_revision,
2417 bad_revision, 2424 bad_revision,
2418 command_to_run, 2425 command_to_run,
2419 metric, 2426 metric,
2420 target_depot) 2427 target_depot)
2421 2428
2422 if self.opts.output_buildbot_annotations: 2429 if self.opts.output_buildbot_annotations:
2423 bisect_utils.OutputAnnotationStepClosed() 2430 bisect_utils.OutputAnnotationStepClosed()
2424 2431
2425 if bad_results[1]: 2432 if bad_results[1]:
2426 results.error = ('An error occurred while building and running ' 2433 results.error = ('An error occurred while building and running '
2427 'the \'bad\' reference value. The bisect cannot continue without ' 2434 'the \'bad\' reference value. The bisect cannot continue without '
2428 'a working \'bad\' revision to start from.\n\nError: %s' % 2435 'a working \'bad\' revision to start from.\n\nError: %s' %
2429 bad_results[0]) 2436 bad_results[0])
2430 return results 2437 return results
2431 2438
2432 if good_results[1]: 2439 if good_results[1]:
2433 results.error = ('An error occurred while building and running ' 2440 results.error = ('An error occurred while building and running '
2434 'the \'good\' reference value. The bisect cannot continue without ' 2441 'the \'good\' reference value. The bisect cannot continue without '
2435 'a working \'good\' revision to start from.\n\nError: %s' % 2442 'a working \'good\' revision to start from.\n\nError: %s' %
2436 good_results[0]) 2443 good_results[0])
2437 return results 2444 return results
2438 2445
2439
2440 # We need these reference values to determine if later runs should be 2446 # We need these reference values to determine if later runs should be
2441 # classified as pass or fail. 2447 # classified as pass or fail.
2442 known_bad_value = bad_results[0] 2448 known_bad_value = bad_results[0]
2443 known_good_value = good_results[0] 2449 known_good_value = good_results[0]
2444 2450
2451 # Check the direction of improvement only if the improvement_direction
2452 # option is set to a specific direction (1 for higher is better or -1 for
2453 # lower is better).
2454 improvement_dir = self.opts.improvement_direction
2455 if improvement_dir:
2456 higher_is_better = improvement_dir > 0
2457 if higher_is_better:
2458 message = "Expecting higher values to be better for this metric, "
2459 else:
2460 message = "Expecting lower values to be better for this metric, "
2461 metric_increased = known_bad_value['mean'] > known_good_value['mean']
2462 if metric_increased:
2463 message += "and the metric appears to have increased. "
2464 else:
2465 message += "and the metric appears to have decreased. "
2466 if ((higher_is_better and metric_increased) or
2467 (not higher_is_better and not metric_increased)):
2468 results.error = (message + 'Then, the test results for the ends of '
2469 'the given \'good\' - \'bad\' range of revisions '
2470 'represent an improvement (and not a regression).')
2471 return results
2472 print message, "Therefore we continue to bisect."
2473
2445 # Can just mark the good and bad revisions explicitly here since we 2474 # Can just mark the good and bad revisions explicitly here since we
2446 # already know the results. 2475 # already know the results.
2447 bad_revision_data = revision_data[revision_list[0]] 2476 bad_revision_data = revision_data[revision_list[0]]
2448 bad_revision_data['external'] = bad_results[2] 2477 bad_revision_data['external'] = bad_results[2]
2449 bad_revision_data['perf_time'] = bad_results[3] 2478 bad_revision_data['perf_time'] = bad_results[3]
2450 bad_revision_data['build_time'] = bad_results[4] 2479 bad_revision_data['build_time'] = bad_results[4]
2451 bad_revision_data['passed'] = False 2480 bad_revision_data['passed'] = False
2452 bad_revision_data['value'] = known_bad_value 2481 bad_revision_data['value'] = known_bad_value
2453 2482
2454 good_revision_data = revision_data[revision_list[max_revision]] 2483 good_revision_data = revision_data[revision_list[max_revision]]
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
2932 self.max_time_minutes = 20 2961 self.max_time_minutes = 20
2933 self.metric = None 2962 self.metric = None
2934 self.command = None 2963 self.command = None
2935 self.output_buildbot_annotations = None 2964 self.output_buildbot_annotations = None
2936 self.no_custom_deps = False 2965 self.no_custom_deps = False
2937 self.working_directory = None 2966 self.working_directory = None
2938 self.extra_src = None 2967 self.extra_src = None
2939 self.debug_ignore_build = None 2968 self.debug_ignore_build = None
2940 self.debug_ignore_sync = None 2969 self.debug_ignore_sync = None
2941 self.debug_ignore_perf_test = None 2970 self.debug_ignore_perf_test = None
2971 self.debug_fake_first_test_mean = 0
2942 self.gs_bucket = None 2972 self.gs_bucket = None
2943 self.target_arch = 'ia32' 2973 self.target_arch = 'ia32'
2944 self.target_build_type = 'Release' 2974 self.target_build_type = 'Release'
2945 self.builder_host = None 2975 self.builder_host = None
2946 self.builder_port = None 2976 self.builder_port = None
2947 self.bisect_mode = BISECT_MODE_MEAN 2977 self.bisect_mode = BISECT_MODE_MEAN
2978 self.improvement_direction = 0
2948 2979
2949 @staticmethod 2980 @staticmethod
2950 def _CreateCommandLineParser(): 2981 def _CreateCommandLineParser():
2951 """Creates a parser with bisect options. 2982 """Creates a parser with bisect options.
2952 2983
2953 Returns: 2984 Returns:
2954 An instance of optparse.OptionParser. 2985 An instance of optparse.OptionParser.
2955 """ 2986 """
2956 usage = ('%prog [options] [-- chromium-options]\n' 2987 usage = ('%prog [options] [-- chromium-options]\n'
2957 'Perform binary search on revision history to find a minimal ' 2988 'Perform binary search on revision history to find a minimal '
(...skipping 13 matching lines...) Expand all
2971 ' or svn revision.') 3002 ' or svn revision.')
2972 group.add_option('-g', '--good_revision', 3003 group.add_option('-g', '--good_revision',
2973 type='str', 3004 type='str',
2974 help='A revision to start bisection where performance' + 3005 help='A revision to start bisection where performance' +
2975 ' test is known to pass. Must be earlier than the ' + 3006 ' test is known to pass. Must be earlier than the ' +
2976 'bad revision. May be either a git or svn revision.') 3007 'bad revision. May be either a git or svn revision.')
2977 group.add_option('-m', '--metric', 3008 group.add_option('-m', '--metric',
2978 type='str', 3009 type='str',
2979 help='The desired metric to bisect on. For example ' + 3010 help='The desired metric to bisect on. For example ' +
2980 '"vm_rss_final_b/vm_rss_f_b"') 3011 '"vm_rss_final_b/vm_rss_f_b"')
3012 group.add_option('-d', '--improvement_direction',
3013 type='int',
3014 default=0,
3015 help='An integer number representing the direction of ' +
3016 'improvement. 1 for higher is better, -1 for lower is ' +
3017 'better, 0 for ignore (default).')
2981 group.add_option('-r', '--repeat_test_count', 3018 group.add_option('-r', '--repeat_test_count',
2982 type='int', 3019 type='int',
2983 default=20, 3020 default=20,
2984 help='The number of times to repeat the performance ' 3021 help='The number of times to repeat the performance '
2985 'test. Values will be clamped to range [1, 100]. ' 3022 'test. Values will be clamped to range [1, 100]. '
2986 'Default value is 20.') 3023 'Default value is 20.')
2987 group.add_option('--max_time_minutes', 3024 group.add_option('--max_time_minutes',
2988 type='int', 3025 type='int',
2989 default=20, 3026 default=20,
2990 help='The maximum time (in minutes) to take running the ' 3027 help='The maximum time (in minutes) to take running the '
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
3091 group = optparse.OptionGroup(parser, 'Debug options') 3128 group = optparse.OptionGroup(parser, 'Debug options')
3092 group.add_option('--debug_ignore_build', 3129 group.add_option('--debug_ignore_build',
3093 action='store_true', 3130 action='store_true',
3094 help='DEBUG: Don\'t perform builds.') 3131 help='DEBUG: Don\'t perform builds.')
3095 group.add_option('--debug_ignore_sync', 3132 group.add_option('--debug_ignore_sync',
3096 action='store_true', 3133 action='store_true',
3097 help='DEBUG: Don\'t perform syncs.') 3134 help='DEBUG: Don\'t perform syncs.')
3098 group.add_option('--debug_ignore_perf_test', 3135 group.add_option('--debug_ignore_perf_test',
3099 action='store_true', 3136 action='store_true',
3100 help='DEBUG: Don\'t perform performance tests.') 3137 help='DEBUG: Don\'t perform performance tests.')
3138 group.add_option('--debug_fake_first_test_mean',
3139 type='int',
3140 default='0',
3141 help=('DEBUG: When faking performance tests, return this '
3142 'value as the mean of the first performance test, '
3143 'and return a mean of 0.0 for further tests.'))
3101 parser.add_option_group(group) 3144 parser.add_option_group(group)
3102 return parser 3145 return parser
3103 3146
3104 def ParseCommandLine(self): 3147 def ParseCommandLine(self):
3105 """Parses the command line for bisect options.""" 3148 """Parses the command line for bisect options."""
3106 parser = self._CreateCommandLineParser() 3149 parser = self._CreateCommandLineParser()
3107 opts, _ = parser.parse_args() 3150 opts, _ = parser.parse_args()
3108 3151
3109 try: 3152 try:
3110 if not opts.command: 3153 if not opts.command:
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
3246 # bugs. If you change this, please update the perf dashboard as well. 3289 # bugs. If you change this, please update the perf dashboard as well.
3247 bisect_utils.OutputAnnotationStepStart('Results') 3290 bisect_utils.OutputAnnotationStepStart('Results')
3248 print 'Error: %s' % e.message 3291 print 'Error: %s' % e.message
3249 if opts.output_buildbot_annotations: 3292 if opts.output_buildbot_annotations:
3250 bisect_utils.OutputAnnotationStepClosed() 3293 bisect_utils.OutputAnnotationStepClosed()
3251 return 1 3294 return 1
3252 3295
3253 3296
3254 if __name__ == '__main__': 3297 if __name__ == '__main__':
3255 sys.exit(main()) 3298 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | tools/auto_bisect/bisect_perf_regression_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698