Chromium Code Reviews| 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 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 355 opts.output_buildbot_annotations) | 355 opts.output_buildbot_annotations) |
| 356 elif opts.build_preference == 'msvs': | 356 elif opts.build_preference == 'msvs': |
| 357 assert IsWindows(), 'msvs is only supported on Windows.' | 357 assert IsWindows(), 'msvs is only supported on Windows.' |
| 358 build_success = BuildWithVisualStudio(targets, | 358 build_success = BuildWithVisualStudio(targets, |
| 359 opts.output_buildbot_annotations) | 359 opts.output_buildbot_annotations) |
| 360 else: | 360 else: |
| 361 assert False, 'No build system defined.' | 361 assert False, 'No build system defined.' |
| 362 return build_success | 362 return build_success |
| 363 | 363 |
| 364 | 364 |
| 365 class AndroidBuilder(Builder): | |
| 366 """AndroidBuilder is used to build on android.""" | |
| 367 def InstallAPK(self, opts): | |
| 368 """Installs apk to device. | |
| 369 | |
| 370 Args: | |
| 371 opts: The options parsed from the command line. | |
| 372 | |
| 373 Returns: | |
| 374 True if successful. | |
| 375 """ | |
| 376 path_to_tool = os.path.join('build', 'android', 'adb_install_apk.py') | |
| 377 cmd = [path_to_tool, '--apk', 'ContentShell.apk', '--apk_package', | |
| 378 'org.chromium.content_shell_apk', '--release'] | |
| 379 (_, return_code) = RunProcess(cmd, opts.output_buildbot_annotations) | |
| 380 return not return_code | |
| 381 | |
| 382 def Build(self, depot, opts): | |
| 383 """Builds the android content shell and other necessary tools using options | |
| 384 passed into the script. | |
| 385 | |
| 386 Args: | |
| 387 depot: Current depot being bisected. | |
| 388 opts: The options parsed from the command line. | |
| 389 | |
| 390 Returns: | |
| 391 True if build was successful. | |
| 392 """ | |
| 393 targets = ['content_shell_apk', 'forwarder2', 'md5sum'] | |
| 394 threads = 16 | |
| 395 if opts.use_goma: | |
| 396 threads = 64 | |
| 397 | |
| 398 build_success = False | |
| 399 if opts.build_preference == 'ninja': | |
| 400 build_success = BuildWithNinja(threads, targets, | |
| 401 opts.output_buildbot_annotations) | |
| 402 else: | |
| 403 assert False, 'No build system defined.' | |
| 404 | |
| 405 if build_success: | |
| 406 build_success = self.InstallAPK(opts) | |
| 407 | |
| 408 return build_success | |
| 409 | |
| 410 | |
| 365 class CrosBuilder(Builder): | 411 class CrosBuilder(Builder): |
| 366 """CrosBuilder is used to build and image ChromeOS/Chromium when cros is the | 412 """CrosBuilder is used to build and image ChromeOS/Chromium when cros is the |
| 367 target platform.""" | 413 target platform.""" |
| 368 def ImageToTarget(self, opts): | 414 def ImageToTarget(self, opts): |
| 369 """Installs latest image to target specified by opts.cros_remote_ip. | 415 """Installs latest image to target specified by opts.cros_remote_ip. |
| 370 | 416 |
| 371 Args: | 417 Args: |
| 372 opts: Program options containing cros_board and cros_remote_ip. | 418 opts: Program options containing cros_board and cros_remote_ip. |
| 373 | 419 |
| 374 Returns: | 420 Returns: |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 721 self.source_control = source_control | 767 self.source_control = source_control |
| 722 self.src_cwd = os.getcwd() | 768 self.src_cwd = os.getcwd() |
| 723 self.cros_cwd = os.path.join(os.getcwd(), '..', 'cros') | 769 self.cros_cwd = os.path.join(os.getcwd(), '..', 'cros') |
| 724 self.depot_cwd = {} | 770 self.depot_cwd = {} |
| 725 self.cleanup_commands = [] | 771 self.cleanup_commands = [] |
| 726 self.warnings = [] | 772 self.warnings = [] |
| 727 self.builder = None | 773 self.builder = None |
| 728 | 774 |
| 729 if opts.target_platform == 'cros': | 775 if opts.target_platform == 'cros': |
| 730 self.builder = CrosBuilder() | 776 self.builder = CrosBuilder() |
| 777 elif opts.target_platform == 'android': | |
| 778 self.builder = AndroidBuilder() | |
| 731 else: | 779 else: |
| 732 self.builder = DesktopBuilder() | 780 self.builder = DesktopBuilder() |
| 733 | 781 |
| 734 # This always starts true since the script grabs latest first. | 782 # This always starts true since the script grabs latest first. |
| 735 self.was_blink = True | 783 self.was_blink = True |
| 736 | 784 |
| 737 for d in DEPOT_NAMES: | 785 for d in DEPOT_NAMES: |
| 738 # The working directory of each depot is just the path to the depot, but | 786 # The working directory of each depot is just the path to the depot, but |
| 739 # since we're already in 'src', we can skip that part. | 787 # since we're already in 'src', we can skip that part. |
| 740 | 788 |
| (...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1290 os.chdir(self.depot_cwd[current_depot]) | 1338 os.chdir(self.depot_cwd[current_depot]) |
| 1291 | 1339 |
| 1292 depot_revision_list = self.GetRevisionList(current_depot, | 1340 depot_revision_list = self.GetRevisionList(current_depot, |
| 1293 end_revision, | 1341 end_revision, |
| 1294 start_revision) | 1342 start_revision) |
| 1295 | 1343 |
| 1296 os.chdir(old_cwd) | 1344 os.chdir(old_cwd) |
| 1297 | 1345 |
| 1298 return depot_revision_list | 1346 return depot_revision_list |
| 1299 | 1347 |
| 1300 def GatherReferenceValues(self, good_rev, bad_rev, cmd, metric): | 1348 def GatherReferenceValues(self, good_rev, bad_rev, cmd, metric, tgt_depot): |
|
tonyg
2013/06/07 21:02:26
The style guide frowns on abbreviations like this.
shatch
2013/06/07 21:57:39
Done.
| |
| 1301 """Gathers reference values by running the performance tests on the | 1349 """Gathers reference values by running the performance tests on the |
| 1302 known good and bad revisions. | 1350 known good and bad revisions. |
| 1303 | 1351 |
| 1304 Args: | 1352 Args: |
| 1305 good_rev: The last known good revision where the performance regression | 1353 good_rev: The last known good revision where the performance regression |
| 1306 has not occurred yet. | 1354 has not occurred yet. |
| 1307 bad_rev: A revision where the performance regression has already occurred. | 1355 bad_rev: A revision where the performance regression has already occurred. |
| 1308 cmd: The command to execute the performance test. | 1356 cmd: The command to execute the performance test. |
| 1309 metric: The metric being tested for regression. | 1357 metric: The metric being tested for regression. |
| 1310 | 1358 |
| 1311 Returns: | 1359 Returns: |
| 1312 A tuple with the results of building and running each revision. | 1360 A tuple with the results of building and running each revision. |
| 1313 """ | 1361 """ |
| 1314 bad_run_results = self.SyncBuildAndRunRevision(bad_rev, | 1362 bad_run_results = self.SyncBuildAndRunRevision(bad_rev, |
| 1315 self.opts.target_platform, | 1363 tgt_depot, |
| 1316 cmd, | 1364 cmd, |
| 1317 metric) | 1365 metric) |
| 1318 | 1366 |
| 1319 good_run_results = None | 1367 good_run_results = None |
| 1320 | 1368 |
| 1321 if not bad_run_results[1]: | 1369 if not bad_run_results[1]: |
| 1322 good_run_results = self.SyncBuildAndRunRevision(good_rev, | 1370 good_run_results = self.SyncBuildAndRunRevision(good_rev, |
| 1323 self.opts.target_platform, | 1371 tgt_depot, |
| 1324 cmd, | 1372 cmd, |
| 1325 metric) | 1373 metric) |
| 1326 | 1374 |
| 1327 return (bad_run_results, good_run_results) | 1375 return (bad_run_results, good_run_results) |
| 1328 | 1376 |
| 1329 def AddRevisionsIntoRevisionData(self, revisions, depot, sort, revision_data): | 1377 def AddRevisionsIntoRevisionData(self, revisions, depot, sort, revision_data): |
| 1330 """Adds new revisions to the revision_data dict and initializes them. | 1378 """Adds new revisions to the revision_data dict and initializes them. |
| 1331 | 1379 |
| 1332 Args: | 1380 Args: |
| 1333 revisions: List of revisions to add. | 1381 revisions: List of revisions to add. |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1529 if self.opts.output_buildbot_annotations: | 1577 if self.opts.output_buildbot_annotations: |
| 1530 bisect_utils.OutputAnnotationStepStart('Gathering Reference Values') | 1578 bisect_utils.OutputAnnotationStepStart('Gathering Reference Values') |
| 1531 | 1579 |
| 1532 print 'Gathering reference values for bisection.' | 1580 print 'Gathering reference values for bisection.' |
| 1533 | 1581 |
| 1534 # Perform the performance tests on the good and bad revisions, to get | 1582 # Perform the performance tests on the good and bad revisions, to get |
| 1535 # reference values. | 1583 # reference values. |
| 1536 (bad_results, good_results) = self.GatherReferenceValues(good_revision, | 1584 (bad_results, good_results) = self.GatherReferenceValues(good_revision, |
| 1537 bad_revision, | 1585 bad_revision, |
| 1538 command_to_run, | 1586 command_to_run, |
| 1539 metric) | 1587 metric, |
| 1588 target_depot) | |
| 1540 | 1589 |
| 1541 if self.opts.output_buildbot_annotations: | 1590 if self.opts.output_buildbot_annotations: |
| 1542 bisect_utils.OutputAnnotationStepClosed() | 1591 bisect_utils.OutputAnnotationStepClosed() |
| 1543 | 1592 |
| 1544 if bad_results[1]: | 1593 if bad_results[1]: |
| 1545 results['error'] = bad_results[0] | 1594 results['error'] = bad_results[0] |
| 1546 return results | 1595 return results |
| 1547 | 1596 |
| 1548 if good_results[1]: | 1597 if good_results[1]: |
| 1549 results['error'] = good_results[0] | 1598 results['error'] = good_results[0] |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2069 'Default value is 25 (highest/lowest 25% will be ' | 2118 'Default value is 25 (highest/lowest 25% will be ' |
| 2070 'discarded).') | 2119 'discarded).') |
| 2071 parser.add_option('--build_preference', | 2120 parser.add_option('--build_preference', |
| 2072 type='choice', | 2121 type='choice', |
| 2073 choices=['msvs', 'ninja', 'make'], | 2122 choices=['msvs', 'ninja', 'make'], |
| 2074 help='The preferred build system to use. On linux/mac ' | 2123 help='The preferred build system to use. On linux/mac ' |
| 2075 'the options are make/ninja. On Windows, the options ' | 2124 'the options are make/ninja. On Windows, the options ' |
| 2076 'are msvs/ninja.') | 2125 'are msvs/ninja.') |
| 2077 parser.add_option('--target_platform', | 2126 parser.add_option('--target_platform', |
| 2078 type='choice', | 2127 type='choice', |
| 2079 choices=['chromium', 'cros'], | 2128 choices=['chromium', 'cros', 'android'], |
| 2080 default='chromium', | 2129 default='chromium', |
| 2081 help='The target platform. Choices are "default" (current ' | 2130 help='The target platform. Choices are "chromium" (current ' |
| 2082 'platform, or "cros". If choosing "cros", you ' | 2131 'platform, "cros", or "android". If you specify something ' |
|
tonyg
2013/06/07 21:02:26
I think there should be a ) after platform
shatch
2013/06/07 21:57:39
Done.
| |
| 2083 'must be properly set up to build.') | 2132 'other than "chromium", you must be properly set up to ' |
| 2133 'build that platform.') | |
| 2084 parser.add_option('--cros_board', | 2134 parser.add_option('--cros_board', |
| 2085 type='str', | 2135 type='str', |
| 2086 help='The cros board type to build.') | 2136 help='The cros board type to build.') |
| 2087 parser.add_option('--cros_remote_ip', | 2137 parser.add_option('--cros_remote_ip', |
| 2088 type='str', | 2138 type='str', |
| 2089 help='The remote machine to image to.') | 2139 help='The remote machine to image to.') |
| 2090 parser.add_option('--use_goma', | 2140 parser.add_option('--use_goma', |
| 2091 action="store_true", | 2141 action="store_true", |
| 2092 help='Add a bunch of extra threads for goma.') | 2142 help='Add a bunch of extra threads for goma.') |
| 2093 parser.add_option('--output_buildbot_annotations', | 2143 parser.add_option('--output_buildbot_annotations', |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2150 print 'Error: missing required parameter: --working_directory' | 2200 print 'Error: missing required parameter: --working_directory' |
| 2151 print | 2201 print |
| 2152 parser.print_help() | 2202 parser.print_help() |
| 2153 return 1 | 2203 return 1 |
| 2154 | 2204 |
| 2155 opts.repeat_test_count = min(max(opts.repeat_test_count, 1), 100) | 2205 opts.repeat_test_count = min(max(opts.repeat_test_count, 1), 100) |
| 2156 opts.repeat_test_max_time = min(max(opts.repeat_test_max_time, 1), 60) | 2206 opts.repeat_test_max_time = min(max(opts.repeat_test_max_time, 1), 60) |
| 2157 opts.truncate_percent = min(max(opts.truncate_percent, 0), 25) | 2207 opts.truncate_percent = min(max(opts.truncate_percent, 0), 25) |
| 2158 opts.truncate_percent = opts.truncate_percent / 100.0 | 2208 opts.truncate_percent = opts.truncate_percent / 100.0 |
| 2159 | 2209 |
| 2210 path_to_file = os.path.abspath(os.path.dirname(sys.argv[0])) | |
| 2211 | |
| 2160 metric_values = opts.metric.split('/') | 2212 metric_values = opts.metric.split('/') |
| 2161 if len(metric_values) != 2: | 2213 if len(metric_values) != 2: |
| 2162 print "Invalid metric specified: [%s]" % (opts.metric,) | 2214 print "Invalid metric specified: [%s]" % (opts.metric,) |
| 2163 print | 2215 print |
| 2164 return 1 | 2216 return 1 |
| 2165 | 2217 |
| 2166 if opts.working_directory: | 2218 if opts.working_directory: |
| 2167 if bisect_utils.CreateBisectDirectoryAndSetupDepot(opts): | 2219 if bisect_utils.CreateBisectDirectoryAndSetupDepot(opts): |
| 2168 return 1 | 2220 return 1 |
| 2169 | 2221 |
| 2170 if opts.target_platform == 'cros': | 2222 if not bisect_utils.SetupPlatformBuildEnvironment(opts, path_to_file): |
| 2171 if not bisect_utils.SetupCrosRepo(): | 2223 print 'Error: Failed to set platform environment.' |
| 2172 print 'Error: Failed to grab cros source.' | 2224 print |
| 2173 print | 2225 return 1 |
| 2174 return 1 | |
| 2175 | 2226 |
| 2176 os.chdir(os.path.join(os.getcwd(), 'src')) | 2227 os.chdir(os.path.join(os.getcwd(), 'src')) |
| 2177 | 2228 |
| 2178 if not RemoveBuildFiles(): | 2229 if not RemoveBuildFiles(): |
| 2179 print "Something went wrong removing the build files." | 2230 print "Something went wrong removing the build files." |
| 2180 print | 2231 print |
| 2181 return 1 | 2232 return 1 |
| 2182 | 2233 |
| 2183 if not CheckPlatformSupported(opts): | 2234 if not CheckPlatformSupported(opts): |
| 2184 return 1 | 2235 return 1 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 2211 | 2262 |
| 2212 if not(bisect_results['error']): | 2263 if not(bisect_results['error']): |
| 2213 return 0 | 2264 return 0 |
| 2214 else: | 2265 else: |
| 2215 print 'Error: ' + bisect_results['error'] | 2266 print 'Error: ' + bisect_results['error'] |
| 2216 print | 2267 print |
| 2217 return 1 | 2268 return 1 |
| 2218 | 2269 |
| 2219 if __name__ == '__main__': | 2270 if __name__ == '__main__': |
| 2220 sys.exit(main()) | 2271 sys.exit(main()) |
| OLD | NEW |