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

Side by Side Diff: tools/testing/perf_testing/run_perf_tests.py

Issue 10836249: More tweaks to perf script (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 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 | no next file » | 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/python 1 #!/usr/bin/python
2 2
3 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 3 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
4 # for details. All rights reserved. Use of this source code is governed by a 4 # for details. All rights reserved. Use of this source code is governed by a
5 # BSD-style license that can be found in the LICENSE file. 5 # BSD-style license that can be found in the LICENSE file.
6 6
7 import datetime 7 import datetime
8 import math 8 import math
9 import optparse 9 import optparse
10 import os 10 import os
11 from os.path import dirname, abspath 11 from os.path import dirname, abspath
12 import pickle 12 import pickle
13 import platform 13 import platform
14 import random
14 import re 15 import re
15 import shutil 16 import shutil
16 import stat 17 import stat
17 import subprocess 18 import subprocess
18 import sys 19 import sys
19 import time 20 import time
20 21
21 TOOLS_PATH = os.path.join(dirname(dirname(dirname(abspath(__file__))))) 22 TOOLS_PATH = os.path.join(dirname(dirname(dirname(abspath(__file__)))))
22 TOP_LEVEL_DIR = abspath(os.path.join(dirname(abspath(__file__)), '..', '..', 23 TOP_LEVEL_DIR = abspath(os.path.join(dirname(abspath(__file__)), '..', '..',
23 '..')) 24 '..'))
(...skipping 27 matching lines...) Expand all
51 stdout to 52 stdout to
52 append: True if we want to append to the file instead of overwriting it 53 append: True if we want to append to the file instead of overwriting it
53 std_in: a string that should be written to the process executing to 54 std_in: a string that should be written to the process executing to
54 interact with it (if needed)""" 55 interact with it (if needed)"""
55 if self.verbose: 56 if self.verbose:
56 print ' '.join(cmd_list) 57 print ' '.join(cmd_list)
57 out = subprocess.PIPE 58 out = subprocess.PIPE
58 if outfile: 59 if outfile:
59 mode = 'w' 60 mode = 'w'
60 if append: 61 if append:
61 mode = 'a' 62 mode = 'a+'
62 out = open(outfile, mode) 63 out = open(outfile, mode)
63 if append: 64 if append:
64 # Annoying Windows "feature" -- append doesn't actually append unless 65 # Annoying Windows "feature" -- append doesn't actually append unless
65 # you explicitly go to the end of the file. 66 # you explicitly go to the end of the file.
66 # http://mail.python.org/pipermail/python-list/2009-October/1221859.html 67 # http://mail.python.org/pipermail/python-list/2009-October/1221859.html
67 out.seek(0, os.SEEK_END) 68 out.seek(0, os.SEEK_END)
68 p = subprocess.Popen(cmd_list, stdout = out, stderr=subprocess.PIPE, 69 p = subprocess.Popen(cmd_list, stdout = out, stderr=subprocess.PIPE,
69 stdin=subprocess.PIPE, shell=self.has_shell) 70 stdin=subprocess.PIPE, shell=self.has_shell)
70 output, stderr = p.communicate(std_in) 71 output, stderr = p.communicate(std_in)
71 if output: 72 if output:
(...skipping 15 matching lines...) Expand all
87 os.chdir(DART_REPO_LOC) 88 os.chdir(DART_REPO_LOC)
88 results, _ = self.run_cmd(['svn', 'st']) 89 results, _ = self.run_cmd(['svn', 'st'])
89 for line in results.split('\n'): 90 for line in results.split('\n'):
90 if line.startswith('?'): 91 if line.startswith('?'):
91 to_remove = line.split()[1] 92 to_remove = line.split()[1]
92 if os.path.isdir(to_remove): 93 if os.path.isdir(to_remove):
93 shutil.rmtree(to_remove)#, ignore_errors=True) 94 shutil.rmtree(to_remove)#, ignore_errors=True)
94 else: 95 else:
95 os.remove(to_remove) 96 os.remove(to_remove)
96 97
97 def get_archive(archive_name): 98 def get_archive(self, archive_name):
98 """Wrapper around the pulling down a specific archive from Google Storage. 99 """Wrapper around the pulling down a specific archive from Google Storage.
99 Adds a specific revision argument as needed. 100 Adds a specific revision argument as needed.
100 Returns: The stderr from running this command.""" 101 Returns: The stderr from running this command."""
101 cmd = ['python', os.path.join(DART_REPO_LOC, 'tools', 'get_archive.py'), 102 cmd = ['python', os.path.join(DART_REPO_LOC, 'tools', 'get_archive.py'),
102 archive_name] 103 archive_name]
103 if self.current_revision_num != -1: 104 if self.current_revision_num != -1:
104 cmd += ['-r', revision_num] 105 cmd += ['-r', self.current_revision_num]
105 _, stderr = self.test.test_runner.run_cmd(cmd) 106 _, stderr = self.run_cmd(cmd)
106 return stderr 107 return stderr
107 108
108 def sync_and_build(self, suites, revision_num=''): 109 def sync_and_build(self, suites, revision_num=''):
109 """Make sure we have the latest version of of the repo, and build it. We 110 """Make sure we have the latest version of of the repo, and build it. We
110 begin and end standing in DART_REPO_LOC. 111 begin and end standing in DART_REPO_LOC.
111 112
112 Args: 113 Args:
113 suites: The set of suites that we wish to build. 114 suites: The set of suites that we wish to build.
114 115
115 Returns: 116 Returns:
(...skipping 12 matching lines...) Expand all
128 shutil.copy( 129 shutil.copy(
129 os.path.join(TOP_LEVEL_DIR, 'tools', 'testing', 'run_selenium.py'), 130 os.path.join(TOP_LEVEL_DIR, 'tools', 'testing', 'run_selenium.py'),
130 os.path.join(DART_REPO_LOC, 'tools', 'testing', 'run_selenium.py')) 131 os.path.join(DART_REPO_LOC, 'tools', 'testing', 'run_selenium.py'))
131 132
132 if revision_num == '': 133 if revision_num == '':
133 revision_num = search_for_revision(['svn', 'info']) 134 revision_num = search_for_revision(['svn', 'info'])
134 if revision_num == -1: 135 if revision_num == -1:
135 revision_num = search_for_revision(['git', 'svn', 'info']) 136 revision_num = search_for_revision(['git', 'svn', 'info'])
136 137
137 self.current_revision_num = revision_num 138 self.current_revision_num = revision_num
138 stderr = get_archive('sdk') 139 stderr = self.get_archive('sdk')
139 if not os.path.exists(get_archive_path) or 'InvalidUriError' in stderr: 140 if not os.path.exists(os.path.join(
141 DART_REPO_LOC, 'tools', 'get_archive.py')) \
142 or 'InvalidUriError' in stderr:
140 # Couldn't find the SDK on Google Storage. Build it locally. 143 # Couldn't find the SDK on Google Storage. Build it locally.
141 144
142 # On Windows, the output directory is marked as "Read Only," which causes 145 # On Windows, the output directory is marked as "Read Only," which causes
143 # an error to be thrown when we use shutil.rmtree. This helper function 146 # an error to be thrown when we use shutil.rmtree. This helper function
144 # changes the permissions so we can still delete the directory. 147 # changes the permissions so we can still delete the directory.
145 def on_rm_error(func, path, exc_info): 148 def on_rm_error(func, path, exc_info):
146 if os.path.exists(path): 149 if os.path.exists(path):
147 os.chmod(path, stat.S_IWRITE) 150 os.chmod(path, stat.S_IWRITE)
148 os.unlink(path) 151 os.unlink(path)
149 # TODO(efortuna): Currently always building ia32 architecture because we 152 # TODO(efortuna): Currently always building ia32 architecture because we
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 243
241 def run_test_sequence(self, revision_num='', num_reruns=1): 244 def run_test_sequence(self, revision_num='', num_reruns=1):
242 """Run the set of commands to (possibly) build, run, and post the results 245 """Run the set of commands to (possibly) build, run, and post the results
243 of our tests. Returns 0 on a successful run, 1 if we fail to post results or 246 of our tests. Returns 0 on a successful run, 1 if we fail to post results or
244 the run failed, -1 if the build is broken. 247 the run failed, -1 if the build is broken.
245 """ 248 """
246 suites = [] 249 suites = []
247 success = True 250 success = True
248 if not self.no_build and self.sync_and_build(suites, revision_num) == 1: 251 if not self.no_build and self.sync_and_build(suites, revision_num) == 1:
249 return -1 # The build is broken. 252 return -1 # The build is broken.
250 253
251 for name in self.suite_names: 254 for name in self.suite_names:
252 for run in range(num_reruns): 255 for run in range(num_reruns):
253 suites += [TestBuilder.make_test(name, self)] 256 suites += [TestBuilder.make_test(name, self)]
254 257
255 for test in suites: 258 for test in suites:
256 success = success and test.run() 259 success = success and test.run()
257 if success: 260 if success:
258 return 0 261 return 0
259 else: 262 else:
260 return 1 263 return 1
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 variant: Specifies whether the data was about generated Frog, js, a 420 variant: Specifies whether the data was about generated Frog, js, a
418 combination of both, or Dart depending on the test. 421 combination of both, or Dart depending on the test.
419 revision_number: The revision of the code (and sometimes the revision of 422 revision_number: The revision of the code (and sometimes the revision of
420 dartium). 423 dartium).
421 424
422 Returns: True if the post was successful file.""" 425 Returns: True if the post was successful file."""
423 return post_results.report_results(benchmark_name, score, platform, variant, 426 return post_results.report_results(benchmark_name, score, platform, variant,
424 revision_number, metric) 427 revision_number, metric)
425 428
426 def calculate_geometric_mean(self, platform, variant, svn_revision): 429 def calculate_geometric_mean(self, platform, variant, svn_revision):
427 """Calculate the aggregate geometric mean for JS and frog benchmark sets, 430 """Calculate the aggregate geometric mean for JS and dart2js benchmark sets,
428 given two benchmark dictionaries.""" 431 given two benchmark dictionaries."""
429 geo_mean = 0 432 geo_mean = 0
430 if self.test.is_valid_combination(platform, variant): 433 if self.test.is_valid_combination(platform, variant):
431 for benchmark in self.test.values_list: 434 for benchmark in self.test.values_list:
432 geo_mean += math.log( 435 geo_mean += math.log(
433 self.test.values_dict[platform][variant][benchmark][ 436 self.test.values_dict[platform][variant][benchmark][
434 len(self.test.values_dict[platform][variant][benchmark]) - 1]) 437 len(self.test.values_dict[platform][variant][benchmark]) - 1])
435 438
436 self.test.values_dict[platform][variant]['Geo-Mean'] += \ 439 self.test.values_dict[platform][variant]['Geo-Mean'] += \
437 [math.pow(math.e, geo_mean / len(self.test.values_list))] 440 [math.pow(math.e, geo_mean / len(self.test.values_list))]
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 494
492 class CommonBrowserTest(RuntimePerformanceTest): 495 class CommonBrowserTest(RuntimePerformanceTest):
493 """Runs this basic performance tests (Benchpress, some V8 benchmarks) in the 496 """Runs this basic performance tests (Benchpress, some V8 benchmarks) in the
494 browser.""" 497 browser."""
495 498
496 def __init__(self, test_runner): 499 def __init__(self, test_runner):
497 """Args: 500 """Args:
498 test_runner: Reference to the object that notifies us when to run.""" 501 test_runner: Reference to the object that notifies us when to run."""
499 super(CommonBrowserTest, self).__init__( 502 super(CommonBrowserTest, self).__init__(
500 self.name(), BrowserTester.get_browsers(False), 503 self.name(), BrowserTester.get_browsers(False),
501 'browser', ['js', 'frog', 'dart2js'], 504 'browser', ['js', 'dart2js'],
502 self.get_standalone_benchmarks(), test_runner, 505 self.get_standalone_benchmarks(), test_runner,
503 self.CommonBrowserTester(self), 506 self.CommonBrowserTester(self),
504 self.CommonBrowserFileProcessor(self)) 507 self.CommonBrowserFileProcessor(self))
505 508
506 @staticmethod 509 @staticmethod
507 def name(): 510 def name():
508 return 'browser-perf' 511 return 'browser-perf'
509 512
510 @staticmethod 513 @staticmethod
511 def get_standalone_benchmarks(): 514 def get_standalone_benchmarks():
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 def get_dromaeo_benchmarks(): 661 def get_dromaeo_benchmarks():
659 valid = DromaeoTester.get_valid_dromaeo_tags() 662 valid = DromaeoTester.get_valid_dromaeo_tags()
660 benchmarks = reduce(lambda l1,l2: l1+l2, 663 benchmarks = reduce(lambda l1,l2: l1+l2,
661 [tests for (tag, tests) in 664 [tests for (tag, tests) in
662 DromaeoTester.DROMAEO_BENCHMARKS.values() 665 DromaeoTester.DROMAEO_BENCHMARKS.values()
663 if tag in valid]) 666 if tag in valid])
664 return map(DromaeoTester.legalize_filename, benchmarks) 667 return map(DromaeoTester.legalize_filename, benchmarks)
665 668
666 @staticmethod 669 @staticmethod
667 def get_dromaeo_versions(): 670 def get_dromaeo_versions():
668 return ['js', 'dart2js_dom', 'dart2js_html'] 671 return ['js', 'dart2js_html']
669 672
670 673
671 class DromaeoTest(RuntimePerformanceTest): 674 class DromaeoTest(RuntimePerformanceTest):
672 """Runs Dromaeo tests, in the browser.""" 675 """Runs Dromaeo tests, in the browser."""
673 def __init__(self, test_runner): 676 def __init__(self, test_runner):
674 super(DromaeoTest, self).__init__( 677 super(DromaeoTest, self).__init__(
675 self.name(), 678 self.name(),
676 BrowserTester.get_browsers(True), 679 BrowserTester.get_browsers(True),
677 'browser', 680 'browser',
678 DromaeoTester.get_dromaeo_versions(), 681 DromaeoTester.get_dromaeo_versions(),
(...skipping 21 matching lines...) Expand all
700 """Move the appropriate version of ChromeDriver onto the path. 703 """Move the appropriate version of ChromeDriver onto the path.
701 TODO(efortuna): This is a total hack because the latest version of Chrome 704 TODO(efortuna): This is a total hack because the latest version of Chrome
702 (Dartium builds) requires a different version of ChromeDriver, that is 705 (Dartium builds) requires a different version of ChromeDriver, that is
703 incompatible with the release or beta Chrome and vice versa. Remove these 706 incompatible with the release or beta Chrome and vice versa. Remove these
704 shenanigans once we're back to both versions of Chrome using the same 707 shenanigans once we're back to both versions of Chrome using the same
705 version of ChromeDriver. IMPORTANT NOTE: This assumes your chromedriver is 708 version of ChromeDriver. IMPORTANT NOTE: This assumes your chromedriver is
706 in the default location (inside depot_tools). 709 in the default location (inside depot_tools).
707 """ 710 """
708 current_dir = os.getcwd() 711 current_dir = os.getcwd()
709 self.test.test_runner.get_archive('chromedriver') 712 self.test.test_runner.get_archive('chromedriver')
710 self.test.test_runner.run_cmd(['python', os.path.join(
711 path = os.environ['PATH'].split(os.pathsep) 713 path = os.environ['PATH'].split(os.pathsep)
712 orig_chromedriver_path = os.path.join(DART_REPO_LOC, 'tools', 'testing', 714 orig_chromedriver_path = os.path.join(DART_REPO_LOC, 'tools', 'testing',
713 'orig-chromedriver') 715 'orig-chromedriver')
714 dartium_chromedriver_path = os.path.join(DART_REPO_LOC, 'tools', 716 dartium_chromedriver_path = os.path.join(DART_REPO_LOC, 'tools',
715 'testing', 717 'testing',
716 'dartium-chromedriver') 718 'dartium-chromedriver')
717 extension = '' 719 extension = ''
718 if platform.system() == 'Windows': 720 if platform.system() == 'Windows':
719 extension = '.exe' 721 extension = '.exe'
720 722
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 upload_success = upload_success and self.report_results( 843 upload_success = upload_success and self.report_results(
842 name, score, browser, version, revision_num, 844 name, score, browser, version, revision_num,
843 self.get_score_type(name)) 845 self.get_score_type(name))
844 else: 846 else:
845 upload_success = False 847 upload_success = False
846 848
847 f.close() 849 f.close()
848 self.calculate_geometric_mean(browser, version, revision_num) 850 self.calculate_geometric_mean(browser, version, revision_num)
849 return upload_success 851 return upload_success
850 852
851
852 class DromaeoSizeTest(Test):
853 """Run tests to determine the compiled file output size of Dromaeo."""
854 def __init__(self, test_runner):
855 super(DromaeoSizeTest, self).__init__(
856 self.name(),
857 ['commandline'], ['dart', 'frog_dom', 'frog_html',
858 'frog_htmlidiomatic'],
859 DromaeoTester.DROMAEO_BENCHMARKS.keys(), test_runner,
860 self.DromaeoSizeTester(self),
861 self.DromaeoSizeProcessor(self), extra_metrics=['sum'])
862
863 @staticmethod
864 def name():
865 return 'dromaeo-size'
866
867
868 class DromaeoSizeTester(DromaeoTester):
869 def run_tests(self):
870 # Build tests.
871 dromaeo_path = os.path.join('samples', 'third_party', 'dromaeo')
872 current_path = os.getcwd()
873 os.chdir(dromaeo_path)
874 self.test.test_runner.run_cmd(
875 ['python', os.path.join('generate_dart2js_tests.py')])
876 self.test.test_runner.get_archive('dartium')
877 os.chdir(current_path)
878
879 self.test.trace_file = os.path.join(TOP_LEVEL_DIR,
880 'tools', 'testing', 'perf_testing', self.test.result_folder_name,
881 self.test.result_folder_name + self.test.cur_time)
882 self.add_svn_revision_to_trace(self.test.trace_file)
883
884 variants = [
885 ('frog_dom', ''),
886 ('frog_html', '-html'),
887 ('frog_htmlidiomatic', '-htmlidiomatic')]
888
889 test_path = os.path.join(dromaeo_path, 'tests')
890 frog_path = os.path.join(test_path, 'frog')
891 total_size = {}
892 for (variant, _) in variants:
893 total_size[variant] = 0
894 total_dart_size = 0
895 for suite in DromaeoTester.DROMAEO_BENCHMARKS.keys():
896 dart_size = 0
897 try:
898 dart_size = os.path.getsize(os.path.join(test_path,
899 'dom-%s.dart' % suite))
900 except OSError:
901 pass #If compilation failed, continue on running other tests.
902
903 total_dart_size += dart_size
904 self.test.test_runner.run_cmd(
905 ['echo', 'Size (dart, %s): %s' % (suite, str(dart_size))],
906 self.test.trace_file, append=True)
907
908 for (variant, suffix) in variants:
909 name = 'dom-%s%s.dart.js' % (suite, suffix)
910 js_size = 0
911 try:
912 # TODO(vsm): Strip comments at least. Consider compression.
913 js_size = os.path.getsize(os.path.join(frog_path, name))
914 except OSError:
915 pass #If compilation failed, continue on running other tests.
916
917 total_size[variant] += js_size
918 self.test.test_runner.run_cmd(
919 ['echo', 'Size (%s, %s): %s' % (variant, suite, str(js_size))],
920 self.test.trace_file, append=True)
921
922 self.test.test_runner.run_cmd(
923 ['echo', 'Size (dart, %s): %s' % (total_dart_size,
924 self.test.extra_metrics[0])],
925 self.test.trace_file, append=True)
926 for (variant, _) in variants:
927 self.test.test_runner.run_cmd(
928 ['echo', 'Size (%s, %s): %s' % (variant, self.test.extra_metrics[0],
929 total_size[variant])],
930 self.test.trace_file, append=True)
931
932
933 class DromaeoSizeProcessor(Processor):
934 def process_file(self, afile, should_post_file):
935 """Pull all the relevant information out of a given tracefile.
936
937 Args:
938 afile: is the filename string we will be processing.
939 Returns: True if we successfully posted our data to storage."""
940 os.chdir(os.path.join(TOP_LEVEL_DIR, 'tools',
941 'testing', 'perf_testing'))
942 f = self.open_trace_file(afile, should_post_file)
943 tabulate_data = False
944 revision_num = 0
945 revision_pattern = r'Revision: (\d+)'
946 result_pattern = r'Size \((\w+), ([a-zA-Z0-9-]+)\): (\d+)'
947
948 upload_success = True
949 for line in f.readlines():
950 rev = re.match(revision_pattern, line.strip())
951 if rev:
952 revision_num = int(rev.group(1))
953 continue
954
955 result = re.match(result_pattern, line.strip())
956 if result:
957 variant = result.group(1)
958 metric = result.group(2)
959 num = result.group(3)
960 if num.find('.') == -1:
961 num = int(num)
962 else:
963 num = float(num)
964 self.test.values_dict['commandline'][variant][metric] += [num]
965 self.test.revision_dict['commandline'][variant][metric] += \
966 [revision_num]
967 if not self.test.test_runner.no_upload and should_post_file:
968 upload_success = upload_success and self.report_results(
969 metric, num, 'commandline', variant, revision_num,
970 self.get_score_type(metric))
971 else:
972 upload_success = False
973
974 f.close()
975 return upload_success
976
977 def get_score_type(self, metric):
978 return self.CODE_SIZE
979
980
981 class CompileTimeAndSizeTest(Test):
982 """Run tests to determine how long frogc takes to compile, and the compiled
983 file output size of some benchmarking files.
984 Note: This test is now 'deprecated' since frog is no longer in the sdk. We
985 just return the last numbers found for frog."""
986 def __init__(self, test_runner):
987 """Reference to the test_runner object that notifies us when to begin
988 testing."""
989 super(CompileTimeAndSizeTest, self).__init__(
990 self.name(), ['commandline'], ['dart2js'], ['swarm'],
991 test_runner, self.CompileTester(self),
992 self.CompileProcessor(self))
993 self.dart_compiler = os.path.join(
994 DART_REPO_LOC, utils.GetBuildRoot(utils.GuessOS(),
995 'release', 'ia32'), 'dart-sdk', 'bin', 'dart2js')
996 _suffix = ''
997 if platform.system() == 'Windows':
998 _suffix = '.exe'
999 self.failure_threshold = {'swarm' : 100}
1000
1001 @staticmethod
1002 def name():
1003 return 'time-size'
1004
1005 class CompileTester(Tester):
1006 def run_tests(self):
1007 self.test.trace_file = os.path.join(TOP_LEVEL_DIR,
1008 'tools', 'testing', 'perf_testing',
1009 self.test.result_folder_name,
1010 self.test.result_folder_name + self.test.cur_time)
1011
1012 self.add_svn_revision_to_trace(self.test.trace_file)
1013
1014 self.test.test_runner.run_cmd(
1015 ['./xcodebuild/ReleaseIA32/dart-sdk/dart2js', '-c', '-o',
1016 'swarm-result', os.path.join('samples', 'swarm', 'swarm.dart')])
1017 swarm_size = 0
1018 try:
1019 swarm_size = os.path.getsize('swarm-result')
1020 except OSError:
1021 pass #If compilation failed, continue on running other tests.
1022
1023 self.test.test_runner.run_cmd(
1024 ['echo', '%d Generated checked swarm size' % swarm_size],
1025 self.test.trace_file, append=True)
1026
1027 class CompileProcessor(Processor):
1028 def process_file(self, afile, should_post_file):
1029 """Pull all the relevant information out of a given tracefile.
1030
1031 Args:
1032 afile: is the filename string we will be processing.
1033 Returns: True if we successfully posted our data to storage."""
1034 os.chdir(os.path.join(TOP_LEVEL_DIR, 'tools',
1035 'testing', 'perf_testing'))
1036 f = self.open_trace_file(afile, should_post_file)
1037 tabulate_data = False
1038 revision_num = 0
1039 upload_success = True
1040 for line in f.readlines():
1041 tokens = line.split()
1042 if 'Revision' in line:
1043 revision_num = int(line.split()[1])
1044 else:
1045 for metric in self.test.values_list:
1046 if metric in line:
1047 num = tokens[0]
1048 if num.find('.') == -1:
1049 num = int(num)
1050 else:
1051 num = float(num)
1052 self.test.values_dict['commandline']['dart2js'][metric] += [num]
1053 self.test.revision_dict['commandline']['dart2js'][metric] += \
1054 [revision_num]
1055 score_type = self.get_score_type(metric)
1056 if not self.test.test_runner.no_upload and should_post_file:
1057 if num < self.test.failure_threshold[metric]:
1058 num = 0
1059 upload_success = upload_success and self.report_results(
1060 metric, num, 'commandline', 'dart2js', revision_num,
1061 score_type)
1062 else:
1063 upload_success = False
1064 if revision_num != 0:
1065 for metric in self.test.values_list:
1066 try:
1067 self.test.revision_dict['commandline']['dart2js'][metric].pop()
1068 self.test.revision_dict['commandline']['dart2js'][metric] += \
1069 [revision_num]
1070 # Fill in 0 if compilation failed.
1071 if self.test.values_dict['commandline']['dart2js'][metric][-1] < \
1072 self.test.failure_threshold[metric]:
1073 self.test.values_dict['commandline']['dart2js'][metric] += [0]
1074 self.test.revision_dict['commandline']['dart2js'][metric] += \
1075 [revision_num]
1076 except IndexError:
1077 # We tried to pop from an empty list. This happens if the first
1078 # trace file we encounter is incomplete.
1079 pass
1080
1081 f.close()
1082 return upload_success
1083
1084 def get_score_type(self, metric):
1085 if 'Compiling' in metric or 'Bootstrapping' in metric:
1086 return self.COMPILE_TIME
1087 return self.CODE_SIZE
1088
1089 class TestBuilder(object): 853 class TestBuilder(object):
1090 """Construct the desired test object.""" 854 """Construct the desired test object."""
1091 available_suites = dict((suite.name(), suite) for suite in [ 855 available_suites = dict((suite.name(), suite) for suite in [
1092 CompileTimeAndSizeTest, CommonBrowserTest, DromaeoTest, DromaeoSizeTest]) 856 CommonBrowserTest, DromaeoTest])
1093 857
1094 @staticmethod 858 @staticmethod
1095 def make_test(test_name, test_runner): 859 def make_test(test_name, test_runner):
1096 return TestBuilder.available_suites[test_name](test_runner) 860 return TestBuilder.available_suites[test_name](test_runner)
1097 861
1098 @staticmethod 862 @staticmethod
1099 def available_suite_names(): 863 def available_suite_names():
1100 return TestBuilder.available_suites.keys() 864 return TestBuilder.available_suites.keys()
1101 865
1102 def search_for_revision(svn_info_command): 866 def search_for_revision(svn_info_command):
(...skipping 19 matching lines...) Expand all
1122 f.close() 886 f.close()
1123 f = open(filename, 'r+') 887 f = open(filename, 'r+')
1124 result_set = pickle.load(f) 888 result_set = pickle.load(f)
1125 if revision_num: 889 if revision_num:
1126 f.seek(0) 890 f.seek(0)
1127 result_set.add(revision_num) 891 result_set.add(revision_num)
1128 pickle.dump(result_set, f) 892 pickle.dump(result_set, f)
1129 f.close() 893 f.close()
1130 return result_set 894 return result_set
1131 895
896 def fill_in_back_history(results_set, runner):
897 """ Fill in back history performance data. This is done one of two ways, with
898 equal probability of trying each way (falling back on the sequential version
899 as our data becomes more densely populated)."""
900 has_run_extra = False
901 os.chdir(DART_REPO_LOC)
902 revision_num = int(search_for_revision(['svn', 'info']))
903 if revision_num == -1:
904 revision_num = int(search_for_revision(['git', 'svn', 'info']))
vsm 2012/08/15 15:27:32 Nit: I'd fold the previous 4 lines into search_for
Emily Fortuna 2012/08/15 22:10:10 Done.
905 os.chdir(TOP_LEVEL_DIR)
906
907 def try_to_run_additional(revision_number):
908 """Determine the number of results we have stored for a particular revision
909 number, and if it is less than 10, run some extra tests.
910 Args:
911 - revision_number: the revision whose performance we want to potentially
912 test."""
913 print 'running %s~~~~~~~~~' % revision_number
914 a_test = TestBuilder.make_test(runner.suite_names[0], runner)
915 benchmark_name = a_test.values_list[0]
916 platform_name = a_test.platform_list[0]
917 variant = a_test.values_dict[platform_name].keys()[0]
918 num_results = post_results.get_num_results(benchmark_name,
919 platform_name, variant, revision_number,
920 a_test.file_processor.get_score_type(benchmark_name))
921 if 10 - num_results < 2 and num_results >= 0:
vsm 2012/08/15 15:27:32 This looks fishy. "10 - num_results < 2" is equiv
Emily Fortuna 2012/08/15 22:10:10 num_results returns -1 if it has an error connecti
922 reruns = 10 - num_results
923 else:
924 reruns = 2
925 run = runner.run_test_sequence(revision_num=str(revision_number),
926 num_reruns=reruns)
927 if run == 0 and num_results + reruns >= 10:
928 results_set = update_set_of_done_cls(revision_number)
929 else:
930 return False
931 return True
932
933 if random.choice([True, False]):
934 # Select a random CL number, with greater likelihood of selecting a CL in
935 # the more recent history than the distant past (using a simplified weighted
936 # bucket algorithm). If that CL has less than 10 runs, run additional. If it
937 # already has 10 runs, look for another CL number that is not yet have all
938 # of its additional runs (do this up to 15 times).
939 tries = 0
940 thousands_list = range(1, int(revision_num)/1000 + 1)
941 weighted_total = sum(thousands_list)
942 generated_random_number = random.randint(0, weighted_total - 1)
943 for i in list(reversed(thousands_list)):
944 thousands = thousands_list[i - 1]
945 weighted_total -= thousands_list[i - 1]
946 if weighted_total <= generated_random_number:
947 break
948 while tries < 15 and not has_run_extra:
949 rev = thousands * 1000 + random.randrange(0,
950 int(revision_num) -
951 int(math.pow(10, int(math.floor(math.log10(int(revision_num))))) + 1))
952 has_run_extra = try_to_run_additional(rev)
953 tries += 1
954
955 if not has_run_extra:
956 # Try to get up to 10 runs of each CL, starting with the most recent
957 # CL that does not yet have 10 runs. But only perform a set of extra
958 # runs at most 2 at a time before
959 # checking to see if new code has been checked in.
960 while revision_num > 0 and not has_run_extra:
961 if revision_num not in results_set:
962 has_run_extra = try_to_run_additional(revision_num)
963 revision_num -= 1
964 if not has_run_extra:
965 # No more extra back-runs to do (for now). Wait for new code.
966 time.sleep(200)
967 return results_set
968
1132 def main(): 969 def main():
1133 runner = TestRunner() 970 runner = TestRunner()
1134 continuous = runner.parse_args() 971 continuous = runner.parse_args()
1135 972
1136 if not os.path.exists(DART_REPO_LOC): 973 if not os.path.exists(DART_REPO_LOC):
1137 os.mkdir(dirname(DART_REPO_LOC)) 974 os.mkdir(dirname(DART_REPO_LOC))
1138 os.chdir(dirname(DART_REPO_LOC)) 975 os.chdir(dirname(DART_REPO_LOC))
1139 p = subprocess.Popen('gclient config https://dart.googlecode.com/svn/' + 976 p = subprocess.Popen('gclient config https://dart.googlecode.com/svn/' +
1140 'branches/bleeding_edge/deps/all.deps', 977 'branches/bleeding_edge/deps/all.deps',
1141 stdout=subprocess.PIPE, stderr=subprocess.PIPE, 978 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
1142 shell=True) 979 shell=True)
1143 p.communicate() 980 p.communicate()
1144 if continuous: 981 if continuous:
1145 while True: 982 while True:
1146 results_set = update_set_of_done_cls() 983 results_set = update_set_of_done_cls()
1147 if runner.has_new_code(): 984 if runner.has_new_code():
1148 runner.run_test_sequence() 985 runner.run_test_sequence()
1149 else: 986 else:
1150 # Try to get up to 10 runs of each CL, starting with the most recent CL 987 results_set = fill_in_back_history(results_set, runner)
1151 # that does not yet have 10 runs. But only perform a set of extra runs
1152 # at most 10 at a time (get all the extra runs for one CL) before
1153 # checking to see if new code has been checked in.
1154 has_run_extra = False
1155 revision_num = int(search_for_revision(['svn', 'info']))
1156 if revision_num == -1:
1157 revision_num = int(search_for_revision(['git', 'svn', 'info']))
1158
1159 # No need to track the performance before revision 3000. That's way in
1160 # the past.
1161 while revision_num > 3000 and not has_run_extra:
1162 if revision_num not in results_set:
1163 a_test = TestBuilder.make_test(runner.suite_names[0], runner)
1164 benchmark_name = a_test.values_list[0]
1165 platform_name = a_test.platform_list[0]
1166 variant = a_test.values_dict[platform_name].keys()[0]
1167 number_of_results = post_results.get_num_results(benchmark_name,
1168 platform_name, variant, revision_num,
1169 a_test.file_processor.get_score_type(benchmark_name))
1170 if number_of_results < 10 and number_of_results >= 0:
1171 run = runner.run_test_sequence(revision_num=str(revision_num),
1172 num_reruns=(10-number_of_results))
1173 if run == 0:
1174 has_run_extra = True
1175 results_set = update_set_of_done_cls(revision_num)
1176 revision_num -= 1
1177 # No more extra back-runs to do (for now). Wait for new code.
1178 time.sleep(200)
1179 else: 988 else:
1180 runner.run_test_sequence() 989 runner.run_test_sequence()
1181 990
1182 if __name__ == '__main__': 991 if __name__ == '__main__':
1183 main() 992 main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698