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

Side by Side Diff: tools/bisect-perf-regression.py

Issue 295133002: Check build status by parsing tryserver buildbot JSON. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | tools/post_perf_builder_job.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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 1499 matching lines...) Expand 10 before | Expand all | Expand 10 after
1567 downloaded_file = os.path.join( 1567 downloaded_file = os.path.join(
1568 abs_build_dir, 1568 abs_build_dir,
1569 GetZipFileName(revision, self.opts.target_arch, patch_sha)) 1569 GetZipFileName(revision, self.opts.target_arch, patch_sha))
1570 1570
1571 fetch_build_func = lambda: FetchFromCloudStorage(self.opts.gs_bucket, 1571 fetch_build_func = lambda: FetchFromCloudStorage(self.opts.gs_bucket,
1572 source_file, 1572 source_file,
1573 abs_build_dir) 1573 abs_build_dir)
1574 1574
1575 if not fetch_build_func(): 1575 if not fetch_build_func():
1576 if not self.PostBuildRequestAndWait(revision, 1576 if not self.PostBuildRequestAndWait(revision,
1577 condition=fetch_build_func, 1577 condition=fetch_build_func,
ghost stip (do not use) 2014/05/30 22:36:31 you should rename condition= to fetch_build=, righ
1578 patch=patch): 1578 patch=patch):
1579 raise RuntimeError('Somewthing went wrong while processing build' 1579 raise RuntimeError('Somewthing went wrong while processing build'
1580 'request for: %s' % revision) 1580 'request for: %s' % revision)
1581 # Generic name for the archive, created when archive file is extracted. 1581 # Generic name for the archive, created when archive file is extracted.
1582 output_dir = os.path.join( 1582 output_dir = os.path.join(
1583 abs_build_dir, GetZipFileName(target_arch=self.opts.target_arch)) 1583 abs_build_dir, GetZipFileName(target_arch=self.opts.target_arch))
1584 # Unzip build archive directory. 1584 # Unzip build archive directory.
1585 try: 1585 try:
1586 RmTreeAndMkDir(output_dir, skip_makedir=True) 1586 RmTreeAndMkDir(output_dir, skip_makedir=True)
1587 ExtractZip(downloaded_file, abs_build_dir) 1587 ExtractZip(downloaded_file, abs_build_dir)
(...skipping 11 matching lines...) Expand all
1599 self.BackupOrRestoreOutputdirectory(restore=True) 1599 self.BackupOrRestoreOutputdirectory(restore=True)
1600 # Cleanup any leftovers from unzipping. 1600 # Cleanup any leftovers from unzipping.
1601 if os.path.exists(output_dir): 1601 if os.path.exists(output_dir):
1602 RmTreeAndMkDir(output_dir, skip_makedir=True) 1602 RmTreeAndMkDir(output_dir, skip_makedir=True)
1603 finally: 1603 finally:
1604 # Delete downloaded archive 1604 # Delete downloaded archive
1605 if os.path.exists(downloaded_file): 1605 if os.path.exists(downloaded_file):
1606 os.remove(downloaded_file) 1606 os.remove(downloaded_file)
1607 return False 1607 return False
1608 1608
1609 def PostBuildRequestAndWait(self, revision, condition, patch=None): 1609 def WaitUntilBuildIsReady(self, fetch_build, bot_name, builder_host,
1610 builder_port, max_timeout):
1611 """Waits until build is produced by bisect builder on tryserver.
1612
1613 Args:
1614 fetch_build: Function to check and download build from cloud storage.
1615 bot_name: Builder bot name on tryserver.
1616 builder_host Tryserver hostname.
1617 builder_port: Tryserver port.
1618 max_timeout: Maximum time to wait for the build.
1619
1620 Returns:
1621 True if build exists and download is successful, otherwise throws
1622 RuntimeError exception when time elapse.
1623 """
1624 # Build number on the tryserver.
1625 build_num = None
1626 # Interval to check build on cloud storage.
1627 poll_interval = 60
1628 # Interval to check build status on tryserver.
1629 status_check_interval = 600
1630 last_status_check = time.time()
1631 start_time = time.time()
1632 while True:
1633 # Checks for build on gs://chrome-perf and download if exists.
1634 res = fetch_build()
1635 if res:
1636 return (res, None)
ghost stip (do not use) 2014/05/30 22:36:31 nit: it's slightly clearer to the reader that res
1637 elapsed_status_check = time.time() - last_status_check
1638 # To avoid overloading tryserver with status check requests, we check
1639 # build status for every 10 mins.
1640 if elapsed_status_check > status_check_interval:
1641 last_status_check = time.time()
1642 if not build_num:
1643 # Get the build number on tryserver for the current build.
1644 build_num = bisect_builder.GetBuildNumFromBuilder(
1645 build_request_id, bot_name, builder_host, builder_port)
1646 # Check the status of build using the build number.
1647 # Note: Build is treated as PENDING if build number is not found
1648 # on the the tryserver.
1649 build_status, status_link = bisect_builder.GetBuildStatus(
1650 build_num, bot_name, builder_host, builder_port)
1651 if build_status == bisect_builder.FAILED:
1652 return (False, 'Failed to produce build, log: %s,' % status_link)
1653 elapsed_time = time.time() - start_time
1654 if elapsed_time > max_timeout:
1655 return (False, 'Timed out: %ss without build' % max_timeout)
1656
1657 print 'Time elapsed: %ss without build.' % elapsed_time
1658 time.sleep(poll_interval)
1659
1660 def PostBuildRequestAndWait(self, revision, fetch_build, patch=None):
1610 """POSTs the build request job to the tryserver instance.""" 1661 """POSTs the build request job to the tryserver instance."""
1611 1662
1612 def GetBuilderNameAndBuildTime(target_arch='ia32'): 1663 def GetBuilderNameAndBuildTime(target_arch='ia32'):
1613 """Gets builder bot name and buildtime in seconds based on platform.""" 1664 """Gets builder bot name and buildtime in seconds based on platform."""
1614 # Bot names should match the one listed in tryserver.chromium's 1665 # Bot names should match the one listed in tryserver.chromium's
1615 # master.cfg which produces builds for bisect. 1666 # master.cfg which produces builds for bisect.
1616 if IsWindows(): 1667 if IsWindows():
1617 if Is64BitWindows() and target_arch == 'x64': 1668 if Is64BitWindows() and target_arch == 'x64':
1618 return ('win_perf_bisect_builder', MAX_WIN_BUILD_TIME) 1669 return ('win_perf_bisect_builder', MAX_WIN_BUILD_TIME)
1619 return ('win_perf_bisect_builder', MAX_WIN_BUILD_TIME) 1670 return ('win_perf_bisect_builder', MAX_WIN_BUILD_TIME)
1620 if IsLinux(): 1671 if IsLinux():
1621 return ('linux_perf_bisect_builder', MAX_LINUX_BUILD_TIME) 1672 return ('linux_perf_bisect_builder', MAX_LINUX_BUILD_TIME)
1622 if IsMac(): 1673 if IsMac():
1623 return ('mac_perf_bisect_builder', MAX_MAC_BUILD_TIME) 1674 return ('mac_perf_bisect_builder', MAX_MAC_BUILD_TIME)
1624 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform) 1675 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform)
1625 if not condition: 1676 if not condition:
1626 return False 1677 return False
1627 1678
1628 bot_name, build_timeout = GetBuilderNameAndBuildTime(self.opts.target_arch) 1679 bot_name, build_timeout = GetBuilderNameAndBuildTime(self.opts.target_arch)
1629 1680 builder_host = self.opts.builder_host
1681 builder_port = self.opts.builder_port
1630 # Create a unique ID for each build request posted to try server builders. 1682 # Create a unique ID for each build request posted to try server builders.
1631 # This ID is added to "Reason" property in build's json. 1683 # This ID is added to "Reason" property in build's json.
1632 # TODO: Use this id to track the build status. 1684 build_request_id = GetSHA1HexDigest(
1633 build_request_id = GetSHA1HexDigest('%s-%s' % (revision, patch)) 1685 '%s-%s-%s' % (revision, patch, time.time()))
1634 1686
1635 # Creates a try job description. 1687 # Creates a try job description.
1636 job_args = {'host': self.opts.builder_host, 1688 job_args = {'host': builder_host,
1637 'port': self.opts.builder_port, 1689 'port': builder_port,
1638 'revision': 'src@%s' % revision, 1690 'revision': 'src@%s' % revision,
1639 'bot': bot_name, 1691 'bot': bot_name,
1640 'name': build_request_id 1692 'name': build_request_id
1641 } 1693 }
1642 # Update patch information if supplied. 1694 # Update patch information if supplied.
1643 if patch: 1695 if patch:
1644 job_args['patch'] = patch 1696 job_args['patch'] = patch
1645 # Posts job to build the revision on the server. 1697 # Posts job to build the revision on the server.
1646 if post_perf_builder_job.PostTryJob(job_args): 1698 if bisect_builder.PostTryJob(job_args):
1647 poll_interval = 60 1699 status, error_msg = self.WaitUntilBuildIsReady(
1648 start_time = time.time() 1700 fetch_build, bot_name, builder_host, builder_port, build_timeout)
1649 while True: 1701 if not status:
1650 res = condition() 1702 raise RuntimeError('Error: %s, revision: [%s]' % (error_msg, revision))
1651 if res: 1703 return True
1652 return res
1653 elapsed_time = time.time() - start_time
1654 if elapsed_time > build_timeout:
1655 raise RuntimeError('Timed out while waiting %ds for %s build.' %
1656 (build_timeout, revision))
1657 print ('Time elapsed: %ss, still waiting for %s build' %
1658 (elapsed_time, revision))
1659 time.sleep(poll_interval)
1660 return False 1704 return False
1661 1705
1662 def IsDownloadable(self, depot): 1706 def IsDownloadable(self, depot):
1663 """Checks if build is downloadable based on target platform and depot.""" 1707 """Checks if build is downloadable based on target platform and depot."""
1664 if self.opts.target_platform in ['chromium'] and self.opts.gs_bucket: 1708 if self.opts.target_platform in ['chromium'] and self.opts.gs_bucket:
1665 return (depot == 'chromium' or 1709 return (depot == 'chromium' or
1666 'chromium' in DEPOT_DEPS_NAME[depot]['from'] or 1710 'chromium' in DEPOT_DEPS_NAME[depot]['from'] or
1667 'v8' in DEPOT_DEPS_NAME[depot]['from']) 1711 'v8' in DEPOT_DEPS_NAME[depot]['from'])
1668 return False 1712 return False
1669 1713
(...skipping 2234 matching lines...) Expand 10 before | Expand all | Expand 10 after
3904 # The perf dashboard scrapes the "results" step in order to comment on 3948 # The perf dashboard scrapes the "results" step in order to comment on
3905 # bugs. If you change this, please update the perf dashboard as well. 3949 # bugs. If you change this, please update the perf dashboard as well.
3906 bisect_utils.OutputAnnotationStepStart('Results') 3950 bisect_utils.OutputAnnotationStepStart('Results')
3907 print 'Error: %s' % e.message 3951 print 'Error: %s' % e.message
3908 if opts.output_buildbot_annotations: 3952 if opts.output_buildbot_annotations:
3909 bisect_utils.OutputAnnotationStepClosed() 3953 bisect_utils.OutputAnnotationStepClosed()
3910 return 1 3954 return 1
3911 3955
3912 if __name__ == '__main__': 3956 if __name__ == '__main__':
3913 sys.exit(main()) 3957 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | tools/post_perf_builder_job.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698