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

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

Issue 256593004: [bisect] - Parse DEPS file manually if execfile fails. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Changes from review. Created 6 years, 7 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
« no previous file with comments | « no previous file | tools/bisect-perf-regression_test.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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 # svn: Needed for git workflow to resolve hashes to svn revisions. 69 # svn: Needed for git workflow to resolve hashes to svn revisions.
70 # from: Parent depot that must be bisected before this is bisected. 70 # from: Parent depot that must be bisected before this is bisected.
71 # deps_var: Key name in vars varible in DEPS file that has revision information. 71 # deps_var: Key name in vars varible in DEPS file that has revision information.
72 DEPOT_DEPS_NAME = { 72 DEPOT_DEPS_NAME = {
73 'chromium' : { 73 'chromium' : {
74 "src" : "src", 74 "src" : "src",
75 "recurse" : True, 75 "recurse" : True,
76 "depends" : None, 76 "depends" : None,
77 "from" : ['cros', 'android-chrome'], 77 "from" : ['cros', 'android-chrome'],
78 'viewvc': 'http://src.chromium.org/viewvc/chrome?view=revision&revision=', 78 'viewvc': 'http://src.chromium.org/viewvc/chrome?view=revision&revision=',
79 'deps_var': None 79 'deps_var': 'chromium_rev'
80 }, 80 },
81 'webkit' : { 81 'webkit' : {
82 "src" : "src/third_party/WebKit", 82 "src" : "src/third_party/WebKit",
83 "recurse" : True, 83 "recurse" : True,
84 "depends" : None, 84 "depends" : None,
85 "from" : ['chromium'], 85 "from" : ['chromium'],
86 'viewvc': 'http://src.chromium.org/viewvc/blink?view=revision&revision=', 86 'viewvc': 'http://src.chromium.org/viewvc/blink?view=revision&revision=',
87 'deps_var': 'webkit_revision' 87 'deps_var': 'webkit_revision'
88 }, 88 },
89 'angle' : { 89 'angle' : {
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 681
682 for t in targets: 682 for t in targets:
683 cmd.extend(['/Project', t]) 683 cmd.extend(['/Project', t])
684 684
685 return_code = RunProcess(cmd) 685 return_code = RunProcess(cmd)
686 686
687 return not return_code 687 return not return_code
688 688
689 689
690 def WriteStringToFile(text, file_name): 690 def WriteStringToFile(text, file_name):
691 with open(file_name, "w") as f: 691 try:
692 f.write(text) 692 with open(file_name, "w") as f:
693 f.write(text)
694 except IOError as e:
695 raise RuntimeError('Error writing to file [%s]' % file_name )
693 696
694 697
695 def ReadStringFromFile(file_name): 698 def ReadStringFromFile(file_name):
696 with open(file_name) as f: 699 try:
697 return f.read() 700 with open(file_name) as f:
701 return f.read()
702 except IOError as e:
703 raise RuntimeError('Error reading file [%s]' % file_name )
698 704
699 705
700 def ChangeBackslashToSlashInPatch(diff_text): 706 def ChangeBackslashToSlashInPatch(diff_text):
701 """Formats file paths in the given text to unix-style paths.""" 707 """Formats file paths in the given text to unix-style paths."""
702 if diff_text: 708 if diff_text:
703 diff_lines = diff_text.split('\n') 709 diff_lines = diff_text.split('\n')
704 for i in range(len(diff_lines)): 710 for i in range(len(diff_lines)):
705 if (diff_lines[i].startswith('--- ') or 711 if (diff_lines[i].startswith('--- ') or
706 diff_lines[i].startswith('+++ ')): 712 diff_lines[i].startswith('+++ ')):
707 diff_lines[i] = diff_lines[i].replace('\\', '/') 713 diff_lines[i] = diff_lines[i].replace('\\', '/')
(...skipping 25 matching lines...) Expand all
733 if 'ninja' in os.getenv('GYP_GENERATORS'): 739 if 'ninja' in os.getenv('GYP_GENERATORS'):
734 opts.build_preference = 'ninja' 740 opts.build_preference = 'ninja'
735 else: 741 else:
736 opts.build_preference = 'make' 742 opts.build_preference = 'make'
737 743
738 SetBuildSystemDefault(opts.build_preference) 744 SetBuildSystemDefault(opts.build_preference)
739 745
740 if not bisect_utils.SetupPlatformBuildEnvironment(opts): 746 if not bisect_utils.SetupPlatformBuildEnvironment(opts):
741 raise RuntimeError('Failed to set platform environment.') 747 raise RuntimeError('Failed to set platform environment.')
742 748
743 bisect_utils.RunGClient(['runhooks'])
744
745 @staticmethod 749 @staticmethod
746 def FromOpts(opts): 750 def FromOpts(opts):
747 builder = None 751 builder = None
748 if opts.target_platform == 'cros': 752 if opts.target_platform == 'cros':
749 builder = CrosBuilder(opts) 753 builder = CrosBuilder(opts)
750 elif opts.target_platform == 'android': 754 elif opts.target_platform == 'android':
751 builder = AndroidBuilder(opts) 755 builder = AndroidBuilder(opts)
752 elif opts.target_platform == 'android-chrome': 756 elif opts.target_platform == 'android-chrome':
753 builder = AndroidChromeBuilder(opts) 757 builder = AndroidChromeBuilder(opts)
754 else: 758 else:
(...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 1364
1361 bleeding_edge_revision = None 1365 bleeding_edge_revision = None
1362 1366
1363 for c in commits: 1367 for c in commits:
1364 bleeding_edge_revision = self._GetV8BleedingEdgeFromV8TrunkIfMappable(c) 1368 bleeding_edge_revision = self._GetV8BleedingEdgeFromV8TrunkIfMappable(c)
1365 if bleeding_edge_revision: 1369 if bleeding_edge_revision:
1366 break 1370 break
1367 1371
1368 return bleeding_edge_revision 1372 return bleeding_edge_revision
1369 1373
1370 def Get3rdPartyRevisionsFromCurrentRevision(self, depot, revision): 1374 def _ParseRevisionsFromDEPSFileManually(self, deps_file_contents):
1371 """Parses the DEPS file to determine WebKit/v8/etc... versions. 1375 """Manually parses the vars section of the DEPS file to determine
1376 chromium/blink/etc... revisions.
1372 1377
1373 Returns: 1378 Returns:
1374 A dict in the format {depot:revision} if successful, otherwise None. 1379 A dict in the format {depot:revision} if successful, otherwise None.
1375 """ 1380 """
1376 cwd = os.getcwd() 1381 # We'll parse the "vars" section of the DEPS file.
1377 self.ChangeToDepotWorkingDirectory(depot) 1382 rxp = re.compile('vars = {(?P<vars_body>[^}]+)', re.MULTILINE)
1383 re_results = rxp.search(deps_file_contents)
1384 locals = {}
1378 1385
1379 results = {} 1386 if not re_results:
1387 return None
1380 1388
1381 if depot == 'chromium' or depot == 'android-chrome': 1389 # We should be left with a series of entries in the vars component of
1390 # the DEPS file with the following format:
1391 # 'depot_name': 'revision',
1392 vars_body = re_results.group('vars_body')
1393 rxp = re.compile("'(?P<depot_body>[\w_-]+)':[\s]+'(?P<rev_body>[\w@]+)'",
1394 re.MULTILINE)
1395 re_results = rxp.findall(vars_body)
1396
1397 return dict(re_results)
1398
1399 def _ParseRevisionsFromDEPSFile(self, depot):
1400 """Parses the local DEPS file to determine blink/skia/v8 revisions which may
1401 be needed if the bisect recurses into those depots later.
1402
1403 Args:
1404 depot: Depot being bisected.
1405
1406 Returns:
1407 A dict in the format {depot:revision} if successful, otherwise None.
1408 """
1409 try:
1382 locals = {'Var': lambda _: locals["vars"][_], 1410 locals = {'Var': lambda _: locals["vars"][_],
1383 'From': lambda *args: None} 1411 'From': lambda *args: None}
1384 execfile(bisect_utils.FILE_DEPS_GIT, {}, locals) 1412 execfile(bisect_utils.FILE_DEPS_GIT, {}, locals)
1385 1413 locals = locals['deps']
1386 os.chdir(cwd) 1414 results = {}
1387 1415
1388 rxp = re.compile(".git@(?P<revision>[a-fA-F0-9]+)") 1416 rxp = re.compile(".git@(?P<revision>[a-fA-F0-9]+)")
1389 1417
1390 for d in DEPOT_NAMES: 1418 for d in DEPOT_NAMES:
1391 if DEPOT_DEPS_NAME[d].has_key('platform'): 1419 if DEPOT_DEPS_NAME[d].has_key('platform'):
1392 if DEPOT_DEPS_NAME[d]['platform'] != os.name: 1420 if DEPOT_DEPS_NAME[d]['platform'] != os.name:
1393 continue 1421 continue
1394 1422
1395 if (DEPOT_DEPS_NAME[d]['recurse'] and 1423 if (DEPOT_DEPS_NAME[d]['recurse'] and
1396 depot in DEPOT_DEPS_NAME[d]['from']): 1424 depot in DEPOT_DEPS_NAME[d]['from']):
1397 if (locals['deps'].has_key(DEPOT_DEPS_NAME[d]['src']) or 1425 if (locals.has_key(DEPOT_DEPS_NAME[d]['src']) or
1398 locals['deps'].has_key(DEPOT_DEPS_NAME[d]['src_old'])): 1426 locals.has_key(DEPOT_DEPS_NAME[d]['src_old'])):
1399 if locals['deps'].has_key(DEPOT_DEPS_NAME[d]['src']): 1427 if locals.has_key(DEPOT_DEPS_NAME[d]['src']):
1400 re_results = rxp.search(locals['deps'][DEPOT_DEPS_NAME[d]['src']]) 1428 re_results = rxp.search(locals[DEPOT_DEPS_NAME[d]['src']])
1401 self.depot_cwd[d] = \ 1429 self.depot_cwd[d] = \
1402 os.path.join(self.src_cwd, DEPOT_DEPS_NAME[d]['src'][4:]) 1430 os.path.join(self.src_cwd, DEPOT_DEPS_NAME[d]['src'][4:])
1403 elif locals['deps'].has_key(DEPOT_DEPS_NAME[d]['src_old']): 1431 elif (DEPOT_DEPS_NAME[d].has_key('src_old') and
1432 locals.has_key(DEPOT_DEPS_NAME[d]['src_old'])):
1404 re_results = \ 1433 re_results = \
1405 rxp.search(locals['deps'][DEPOT_DEPS_NAME[d]['src_old']]) 1434 rxp.search(locals[DEPOT_DEPS_NAME[d]['src_old']])
1406 self.depot_cwd[d] = \ 1435 self.depot_cwd[d] = \
1407 os.path.join(self.src_cwd, DEPOT_DEPS_NAME[d]['src_old'][4:]) 1436 os.path.join(self.src_cwd, DEPOT_DEPS_NAME[d]['src_old'][4:])
1408 1437
1409 if re_results: 1438 if re_results:
1410 results[d] = re_results.group('revision') 1439 results[d] = re_results.group('revision')
1411 else: 1440 else:
1412 print 'Couldn\'t parse revision for %s.' % d 1441 warning_text = ('Couldn\'t parse revision for %s while bisecting '
1413 print 1442 '%s' % (d, depot))
1414 return None 1443 if not warningText in self.warnings:
1444 self.warnings.append(warningText)
1415 else: 1445 else:
1416 print 'Couldn\'t find %s while parsing .DEPS.git.' % d 1446 print 'Couldn\'t find %s while parsing .DEPS.git.' % d
1417 print 1447 print
1418 return None 1448 return None
1449 return results
1450 except ImportError:
1451 deps_file_contents = ReadStringFromFile(bisect_utils.FILE_DEPS_GIT)
1452 parse_results = self._ParseRevisionsFromDEPSFileManually(
1453 deps_file_contents)
1454 results = {}
1455 for depot_name, depot_revision in parse_results.iteritems():
1456 depot_revision = depot_revision.strip('@')
1457 print depot_name, depot_revision
1458 for current_name, current_data in DEPOT_DEPS_NAME.iteritems():
1459 if (current_data.has_key('deps_var') and
1460 current_data['deps_var'] == depot_name):
1461 src_name = current_name
1462 results[src_name] = depot_revision
1463 break
1464 return results
1465
1466 def Get3rdPartyRevisionsFromCurrentRevision(self, depot, revision):
1467 """Parses the DEPS file to determine WebKit/v8/etc... versions.
1468
1469 Returns:
1470 A dict in the format {depot:revision} if successful, otherwise None.
1471 """
1472 cwd = os.getcwd()
1473 self.ChangeToDepotWorkingDirectory(depot)
1474
1475 results = {}
1476
1477 if depot == 'chromium' or depot == 'android-chrome':
1478 results = self._ParseRevisionsFromDEPSFile(depot)
1479 os.chdir(cwd)
1419 elif depot == 'cros': 1480 elif depot == 'cros':
1420 cmd = [CROS_SDK_PATH, '--', 'portageq-%s' % self.opts.cros_board, 1481 cmd = [CROS_SDK_PATH, '--', 'portageq-%s' % self.opts.cros_board,
1421 'best_visible', '/build/%s' % self.opts.cros_board, 'ebuild', 1482 'best_visible', '/build/%s' % self.opts.cros_board, 'ebuild',
1422 CROS_CHROMEOS_PATTERN] 1483 CROS_CHROMEOS_PATTERN]
1423 (output, return_code) = RunProcessAndRetrieveOutput(cmd) 1484 (output, return_code) = RunProcessAndRetrieveOutput(cmd)
1424 1485
1425 assert not return_code, 'An error occurred while running' \ 1486 assert not return_code, 'An error occurred while running' \
1426 ' "%s"' % ' '.join(cmd) 1487 ' "%s"' % ' '.join(cmd)
1427 1488
1428 if len(output) > CROS_CHROMEOS_PATTERN: 1489 if len(output) > CROS_CHROMEOS_PATTERN:
(...skipping 2290 matching lines...) Expand 10 before | Expand all | Expand 10 after
3719 # The perf dashboard scrapes the "results" step in order to comment on 3780 # The perf dashboard scrapes the "results" step in order to comment on
3720 # bugs. If you change this, please update the perf dashboard as well. 3781 # bugs. If you change this, please update the perf dashboard as well.
3721 bisect_utils.OutputAnnotationStepStart('Results') 3782 bisect_utils.OutputAnnotationStepStart('Results')
3722 print 'Error: %s' % e.message 3783 print 'Error: %s' % e.message
3723 if opts.output_buildbot_annotations: 3784 if opts.output_buildbot_annotations:
3724 bisect_utils.OutputAnnotationStepClosed() 3785 bisect_utils.OutputAnnotationStepClosed()
3725 return 1 3786 return 1
3726 3787
3727 if __name__ == '__main__': 3788 if __name__ == '__main__':
3728 sys.exit(main()) 3789 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | tools/bisect-perf-regression_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698