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, target_depot): |
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 target_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 target_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 ' |
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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2160 metric_values = opts.metric.split('/') | 2210 metric_values = opts.metric.split('/') |
2161 if len(metric_values) != 2: | 2211 if len(metric_values) != 2: |
2162 print "Invalid metric specified: [%s]" % (opts.metric,) | 2212 print "Invalid metric specified: [%s]" % (opts.metric,) |
2163 print | 2213 print |
2164 return 1 | 2214 return 1 |
2165 | 2215 |
2166 if opts.working_directory: | 2216 if opts.working_directory: |
2167 if bisect_utils.CreateBisectDirectoryAndSetupDepot(opts): | 2217 if bisect_utils.CreateBisectDirectoryAndSetupDepot(opts): |
2168 return 1 | 2218 return 1 |
2169 | 2219 |
2170 if opts.target_platform == 'cros': | 2220 if not bisect_utils.SetupPlatformBuildEnvironment(opts): |
2171 if not bisect_utils.SetupCrosRepo(): | 2221 print 'Error: Failed to set platform environment.' |
2172 print 'Error: Failed to grab cros source.' | 2222 print |
2173 print | 2223 return 1 |
2174 return 1 | |
2175 | 2224 |
2176 os.chdir(os.path.join(os.getcwd(), 'src')) | 2225 os.chdir(os.path.join(os.getcwd(), 'src')) |
2177 | 2226 |
2178 if not RemoveBuildFiles(): | 2227 if not RemoveBuildFiles(): |
2179 print "Something went wrong removing the build files." | 2228 print "Something went wrong removing the build files." |
2180 print | 2229 print |
2181 return 1 | 2230 return 1 |
2182 | 2231 |
2183 if not CheckPlatformSupported(opts): | 2232 if not CheckPlatformSupported(opts): |
2184 return 1 | 2233 return 1 |
(...skipping 26 matching lines...) Expand all Loading... |
2211 | 2260 |
2212 if not(bisect_results['error']): | 2261 if not(bisect_results['error']): |
2213 return 0 | 2262 return 0 |
2214 else: | 2263 else: |
2215 print 'Error: ' + bisect_results['error'] | 2264 print 'Error: ' + bisect_results['error'] |
2216 print | 2265 print |
2217 return 1 | 2266 return 1 |
2218 | 2267 |
2219 if __name__ == '__main__': | 2268 if __name__ == '__main__': |
2220 sys.exit(main()) | 2269 sys.exit(main()) |
OLD | NEW |