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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 47 import shutil | 47 import shutil |
| 48 import StringIO | 48 import StringIO |
| 49 import subprocess | 49 import subprocess |
| 50 import sys | 50 import sys |
| 51 import time | 51 import time |
| 52 import zipfile | 52 import zipfile |
| 53 | 53 |
| 54 sys.path.append(os.path.join(os.path.dirname(__file__), 'telemetry')) | 54 sys.path.append(os.path.join(os.path.dirname(__file__), 'telemetry')) |
| 55 | 55 |
| 56 import bisect_utils | 56 import bisect_utils |
| 57 import post_perf_builder_job | 57 import post_perf_builder_job as bisect_builder |
| 58 from telemetry.page import cloud_storage | 58 from telemetry.page import cloud_storage |
| 59 | 59 |
| 60 # The additional repositories that might need to be bisected. | 60 # The additional repositories that might need to be bisected. |
| 61 # If the repository has any dependant repositories (such as skia/src needs | 61 # If the repository has any dependant repositories (such as skia/src needs |
| 62 # skia/include and skia/gyp to be updated), specify them in the 'depends' | 62 # skia/include and skia/gyp to be updated), specify them in the 'depends' |
| 63 # so that they're synced appropriately. | 63 # so that they're synced appropriately. |
| 64 # Format is: | 64 # Format is: |
| 65 # src: path to the working directory. | 65 # src: path to the working directory. |
| 66 # recurse: True if this repositry will get bisected. | 66 # recurse: True if this repositry will get bisected. |
| 67 # depends: A list of other repositories that are actually part of the same | 67 # depends: A list of other repositories that are actually part of the same |
| (...skipping 1548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1616 return ('win_perf_bisect_builder', MAX_WIN_BUILD_TIME) | 1616 return ('win_perf_bisect_builder', MAX_WIN_BUILD_TIME) |
| 1617 if IsLinux(): | 1617 if IsLinux(): |
| 1618 return ('linux_perf_bisect_builder', MAX_LINUX_BUILD_TIME) | 1618 return ('linux_perf_bisect_builder', MAX_LINUX_BUILD_TIME) |
| 1619 if IsMac(): | 1619 if IsMac(): |
| 1620 return ('mac_perf_bisect_builder', MAX_MAC_BUILD_TIME) | 1620 return ('mac_perf_bisect_builder', MAX_MAC_BUILD_TIME) |
| 1621 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform) | 1621 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform) |
| 1622 if not condition: | 1622 if not condition: |
| 1623 return False | 1623 return False |
| 1624 | 1624 |
| 1625 bot_name, build_timeout = GetBuilderNameAndBuildTime(self.opts.target_arch) | 1625 bot_name, build_timeout = GetBuilderNameAndBuildTime(self.opts.target_arch) |
| 1626 | 1626 # Build number on the tryserver. |
| 1627 build_num = None | |
| 1628 builder_host = self.opts.builder_host | |
| 1629 builder_port = self.opts.builder_port | |
| 1627 # Create a unique ID for each build request posted to try server builders. | 1630 # Create a unique ID for each build request posted to try server builders. |
| 1628 # This ID is added to "Reason" property in build's json. | 1631 # This ID is added to "Reason" property in build's json. |
| 1629 # TODO: Use this id to track the build status. | 1632 build_request_id = GetSHA1HexDigest( |
| 1630 build_request_id = GetSHA1HexDigest('%s-%s' % (revision, patch)) | 1633 '%s-%s-%s' % (revision, patch, time.time())) |
| 1631 | 1634 |
| 1632 # Creates a try job description. | 1635 # Creates a try job description. |
| 1633 job_args = {'host': self.opts.builder_host, | 1636 job_args = {'host': builder_host, |
| 1634 'port': self.opts.builder_port, | 1637 'port': builder_port, |
| 1635 'revision': 'src@%s' % revision, | 1638 'revision': 'src@%s' % revision, |
| 1636 'bot': bot_name, | 1639 'bot': bot_name, |
| 1637 'name': build_request_id | 1640 'name': build_request_id |
| 1638 } | 1641 } |
| 1639 # Update patch information if supplied. | 1642 # Update patch information if supplied. |
| 1640 if patch: | 1643 if patch: |
| 1641 job_args['patch'] = patch | 1644 job_args['patch'] = patch |
| 1642 # Posts job to build the revision on the server. | 1645 # Posts job to build the revision on the server. |
| 1643 if post_perf_builder_job.PostTryJob(job_args): | 1646 if bisect_builder.PostTryJob(job_args): |
| 1644 poll_interval = 60 | 1647 poll_interval = 60 |
| 1648 status_check_interval = 600 | |
| 1649 last_status_check = time.time() | |
| 1645 start_time = time.time() | 1650 start_time = time.time() |
| 1646 while True: | 1651 while True: |
|
qyearsley
2014/05/23 23:17:16
Suggestion: Would it be clearer if this wait-loop
| |
| 1647 res = condition() | 1652 res = condition() |
|
qyearsley
2014/05/23 23:17:16
It's not obvious here that this condition function
| |
| 1648 if res: | 1653 if res: |
| 1649 return res | 1654 return res |
| 1655 elapsed_status_check = time.time() - last_status_check | |
| 1656 # To avoid overloading tryserver with status check requests, we check | |
| 1657 # build status for every 10 mins. | |
| 1658 if elapsed_status_check > status_check_interval: | |
| 1659 last_status_check = time.time() | |
| 1660 if not build_num: | |
| 1661 # Get the build number on tryserver for the current build. | |
| 1662 build_num = bisect_builder.GetBuildNumFromBuilder( | |
| 1663 build_request_id, bot_name, builder_host, builder_port) | |
| 1664 # Check the status of build using the build number. | |
| 1665 # Note: Build is treated as PENDING if build number is not found | |
| 1666 # on the the tryserver. | |
| 1667 build_status, status_link = bisect_builder.GetBuildStatus( | |
| 1668 build_num, bot_name, builder_host, builder_port) | |
| 1669 if build_status == bisect_builder.FAILED: | |
| 1670 raise RuntimeError('Failed to build revision %s, status link %s.' % | |
| 1671 (revision, status_link)) | |
| 1650 elapsed_time = time.time() - start_time | 1672 elapsed_time = time.time() - start_time |
| 1651 if elapsed_time > build_timeout: | 1673 if elapsed_time > build_timeout: |
| 1652 raise RuntimeError('Timed out while waiting %ds for %s build.' % | 1674 raise RuntimeError('Timed out while waiting %ds for %s build.' % |
| 1653 (build_timeout, revision)) | 1675 (build_timeout, revision)) |
| 1654 print ('Time elapsed: %ss, still waiting for %s build' % | 1676 print ('Time elapsed: %ss, still waiting for %s build' % |
| 1655 (elapsed_time, revision)) | 1677 (elapsed_time, revision)) |
| 1656 time.sleep(poll_interval) | 1678 time.sleep(poll_interval) |
| 1657 return False | 1679 return False |
| 1658 | 1680 |
| 1659 def IsDownloadable(self, depot): | 1681 def IsDownloadable(self, depot): |
| (...skipping 2234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3894 # The perf dashboard scrapes the "results" step in order to comment on | 3916 # The perf dashboard scrapes the "results" step in order to comment on |
| 3895 # bugs. If you change this, please update the perf dashboard as well. | 3917 # bugs. If you change this, please update the perf dashboard as well. |
| 3896 bisect_utils.OutputAnnotationStepStart('Results') | 3918 bisect_utils.OutputAnnotationStepStart('Results') |
| 3897 print 'Error: %s' % e.message | 3919 print 'Error: %s' % e.message |
| 3898 if opts.output_buildbot_annotations: | 3920 if opts.output_buildbot_annotations: |
| 3899 bisect_utils.OutputAnnotationStepClosed() | 3921 bisect_utils.OutputAnnotationStepClosed() |
| 3900 return 1 | 3922 return 1 |
| 3901 | 3923 |
| 3902 if __name__ == '__main__': | 3924 if __name__ == '__main__': |
| 3903 sys.exit(main()) | 3925 sys.exit(main()) |
| OLD | NEW |