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 |