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

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

Issue 10210010: Get rid of selfhosted test in perf tracking and fix for uploading data. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 8 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) 2011, the Dart project authors. Please see the AUTHORS file 3 # Copyright (c) 2011, 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 optparse 8 import optparse
9 import os 9 import os
10 from os.path import dirname, abspath 10 from os.path import dirname, abspath
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 104
105 # On Windows, the output directory is marked as "Read Only," which causes an 105 # On Windows, the output directory is marked as "Read Only," which causes an
106 # error to be thrown when we use shutil.rmtree. This helper function changes 106 # error to be thrown when we use shutil.rmtree. This helper function changes
107 # the permissions so we can still delete the directory. 107 # the permissions so we can still delete the directory.
108 def on_rm_error(func, path, exc_info): 108 def on_rm_error(func, path, exc_info):
109 if os.path.exists(path): 109 if os.path.exists(path):
110 os.chmod(path, stat.S_IWRITE) 110 os.chmod(path, stat.S_IWRITE)
111 os.unlink(path) 111 os.unlink(path)
112 # TODO(efortuna): building the sdk locally is a band-aid until all build XXX 112 # TODO(efortuna): building the sdk locally is a band-aid until all build XXX
113 # platform SDKs are hosted in Google storage. Pull from https://sandbox. 113 # platform SDKs are hosted in Google storage. Pull from https://sandbox.
114 # google.com/storage/?arg=dart-dump-render-tree#dart-dump-render-tree%2Fsdk 114 # google.com/storage/?arg=dart-dump-render-tree/sdk/#dart-dump-render-tree%2 Fsdk
115 # eventually. 115 # eventually.
116 # TODO(efortuna): Currently always building ia32 architecture because we 116 # TODO(efortuna): Currently always building ia32 architecture because we
117 # don't have test statistics for what's passing on x64. Eliminate arch 117 # don't have test statistics for what's passing on x64. Eliminate arch
118 # specification when we have tests running on x64, too. 118 # specification when we have tests running on x64, too.
119 shutil.rmtree(os.path.join(os.getcwd(), 119 shutil.rmtree(os.path.join(os.getcwd(),
120 utils.GetBuildRoot(utils.GuessOS(), 'release', 'ia32')), 120 utils.GetBuildRoot(utils.GuessOS(), 'release', 'ia32')),
121 onerror=on_rm_error) 121 onerror=on_rm_error)
122 122
123 for target in TestRunner.get_build_targets(suites): 123 for target in TestRunner.get_build_targets(suites):
124 lines = self.run_cmd([os.path.join('.', 'tools', 'build.py'), '-m', 124 lines = self.run_cmd([os.path.join('.', 'tools', 'build.py'), '-m',
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 parser.add_option('--suites', '-s', dest='suites', help='Run the specified ' 170 parser.add_option('--suites', '-s', dest='suites', help='Run the specified '
171 'comma-separated test suites from set: %s' % \ 171 'comma-separated test suites from set: %s' % \
172 ','.join(TestBuilder.available_suite_names()), 172 ','.join(TestBuilder.available_suite_names()),
173 action='store', default=None) 173 action='store', default=None)
174 parser.add_option('--forever', '-f', dest='continuous', help='Run this scri' 174 parser.add_option('--forever', '-f', dest='continuous', help='Run this scri'
175 'pt forever, always checking for the next svn checkin', 175 'pt forever, always checking for the next svn checkin',
176 action='store_true', default=False) 176 action='store_true', default=False)
177 parser.add_option('--nobuild', '-n', dest='no_build', action='store_true', 177 parser.add_option('--nobuild', '-n', dest='no_build', action='store_true',
178 help='Do not sync with the repository and do not ' 178 help='Do not sync with the repository and do not '
179 'rebuild.', default=False) 179 'rebuild.', default=False)
180 parser.add_option('--upload', '-u', dest='upload', action='store_true',
181 help='Post the results of the run.', default=False)
180 parser.add_option('--verbose', '-v', dest='verbose', help='Print extra ' 182 parser.add_option('--verbose', '-v', dest='verbose', help='Print extra '
181 'debug output', action='store_true', default=False) 183 'debug output', action='store_true', default=False)
182 184
183 args, ignored = parser.parse_args() 185 args, ignored = parser.parse_args()
184 186
185 if not args.suites: 187 if not args.suites:
186 suites = TestBuilder.available_suite_names() 188 suites = TestBuilder.available_suite_names()
187 else: 189 else:
188 suites = [] 190 suites = []
189 suitelist = args.suites.split(',') 191 suitelist = args.suites.split(',')
190 for name in suitelist: 192 for name in suitelist:
191 if name in TestBuilder.available_suite_names(): 193 if name in TestBuilder.available_suite_names():
192 suites.append(name) 194 suites.append(name)
193 else: 195 else:
194 print ('Error: Invalid suite %s not in ' % name) + \ 196 print ('Error: Invalid suite %s not in ' % name) + \
195 '%s' % ','.join(TestBuilder.available_suite_names()) 197 '%s' % ','.join(TestBuilder.available_suite_names())
196 sys.exit(1) 198 sys.exit(1)
197 self.suite_names = suites 199 self.suite_names = suites
198 self.no_build = args.no_build 200 self.no_build = args.no_build
201 self.upload = args.upload
199 self.verbose = args.verbose 202 self.verbose = args.verbose
200 return args.continuous 203 return args.continuous
201 204
202 def run_test_sequence(self): 205 def run_test_sequence(self):
203 """Run the set of commands to (possibly) build, run, and graph the results 206 """Run the set of commands to (possibly) build, run, and graph the results
204 of our tests. 207 of our tests.
205 208
206 Args: 209 Args:
207 suite_names: The "display name" the user enters to specify which 210 suite_names: The "display name" the user enters to specify which
208 benchmark(s) to run. 211 benchmark(s) to run.
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 elif not search_for_revision(['svn', 'info']): 324 elif not search_for_revision(['svn', 'info']):
322 if not search_for_revision(['git', 'svn', 'info']): 325 if not search_for_revision(['git', 'svn', 'info']):
323 self.test.test_runner.run_cmd(['echo', 'Revision: unknown'], outfile) 326 self.test.test_runner.run_cmd(['echo', 'Revision: unknown'], outfile)
324 327
325 328
326 class Processor(object): 329 class Processor(object):
327 """The base level vistor class that processes tests. It contains convenience 330 """The base level vistor class that processes tests. It contains convenience
328 methods that many File Processor objects use. Any class that would like to be 331 methods that many File Processor objects use. Any class that would like to be
329 a ProcessorVisitor must implement the process_file() method.""" 332 a ProcessorVisitor must implement the process_file() method."""
330 333
334 SCORE = 'Score'
335 COMPILE_TIME = 'CompileTime'
336 CODE_SIZE = 'CodeSize'
337
331 def __init__(self, test): 338 def __init__(self, test):
332 self.test = test 339 self.test = test
333 340
334 def prepare(self): 341 def prepare(self):
335 """Perform any initial setup required before the test is run.""" 342 """Perform any initial setup required before the test is run."""
336 pass 343 pass
337 344
338 def report_results(self, benchmark_name, score, platform, variant, 345 def report_results(self, benchmark_name, score, platform, variant,
339 revision_number): 346 revision_number, metric):
340 """Store the results of the benchmark run. 347 """Store the results of the benchmark run.
341 Args: 348 Args:
342 benchmark_name: The name of the individual benchmark. 349 benchmark_name: The name of the individual benchmark.
343 score: The numerical value of this benchmark. 350 score: The numerical value of this benchmark.
344 platform: The platform the test was run on (firefox, command line, etc). 351 platform: The platform the test was run on (firefox, command line, etc).
345 variant: Specifies whether the data was about generated Frog, js, a 352 variant: Specifies whether the data was about generated Frog, js, a
346 combination of both, or Dart depending on the test. 353 combination of both, or Dart depending on the test.
347 revision_number: The revision of the code (and sometimes the revision of 354 revision_number: The revision of the code (and sometimes the revision of
348 dartium). 355 dartium).
349 356
350 Returns: True if the post was successful.""" 357 Returns: True if the post was successful."""
358 # TODO(efortuna): delete results file if returns True.
351 return post_results.report_results(benchmark_name, score, platform, variant, 359 return post_results.report_results(benchmark_name, score, platform, variant,
352 revision_number) 360 revision_number, metric)
353 361
354 362
355 class RuntimePerformanceTest(Test): 363 class RuntimePerformanceTest(Test):
356 """Super class for all runtime performance testing.""" 364 """Super class for all runtime performance testing."""
357 365
358 def __init__(self, result_folder_name, platform_list, platform_type, 366 def __init__(self, result_folder_name, platform_list, platform_type,
359 versions, benchmarks, test_runner, tester, file_processor, 367 versions, benchmarks, test_runner, tester, file_processor,
360 build_targets=['create_sdk']): 368 build_targets=['create_sdk']):
361 """Args: 369 """Args:
362 result_folder_name: The name of the folder where a tracefile of 370 result_folder_name: The name of the folder where a tracefile of
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 else: 494 else:
487 results = line.split('<br />') 495 results = line.split('<br />')
488 for result in results: 496 for result in results:
489 name_and_score = result.split(':') 497 name_and_score = result.split(':')
490 if len(name_and_score) < 2: 498 if len(name_and_score) < 2:
491 break 499 break
492 name = name_and_score[0].strip() 500 name = name_and_score[0].strip()
493 score = name_and_score[1].strip() 501 score = name_and_score[1].strip()
494 if version == 'js' or version == 'v8': 502 if version == 'js' or version == 'v8':
495 version = 'js' 503 version = 'js'
496 self.report_results(name, score, browser, version, revision_num) 504 if self.test.test_runner.upload:
505 self.report_results(name, score, browser, version, revision_num,
506 self.SCORE)
497 507
498 f.close() 508 f.close()
499 509
500 510
501 class DromaeoTester(Tester): 511 class DromaeoTester(Tester):
502 DROMAEO_BENCHMARKS = { 512 DROMAEO_BENCHMARKS = {
503 'attr': ('attributes', [ 513 'attr': ('attributes', [
504 'getAttribute', 514 'getAttribute',
505 'element.property', 515 'element.property',
506 'setAttribute', 516 'setAttribute',
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 662
653 suite_results = re.findall(suite_pattern, line) 663 suite_results = re.findall(suite_pattern, line)
654 if suite_results: 664 if suite_results:
655 for suite_result in suite_results: 665 for suite_result in suite_results:
656 results = re.findall(r'<li>(.*?)</li>', suite_result) 666 results = re.findall(r'<li>(.*?)</li>', suite_result)
657 if results: 667 if results:
658 for result in results: 668 for result in results:
659 r = re.match(result_pattern, result) 669 r = re.match(result_pattern, result)
660 name = DromaeoTester.legalize_filename(r.group(1).strip(':')) 670 name = DromaeoTester.legalize_filename(r.group(1).strip(':'))
661 score = float(r.group(2)) 671 score = float(r.group(2))
662 self.report_results(name, score, browser, version, revision_num) 672 if self.test.test_runner.upload:
673 self.report_results(name, score, browser, version,
674 revision_num, self.SCORE)
663 675
664 f.close() 676 f.close()
665 677
666 678
667 class DromaeoSizeTest(Test): 679 class DromaeoSizeTest(Test):
668 """Run tests to determine the compiled file output size of Dromaeo.""" 680 """Run tests to determine the compiled file output size of Dromaeo."""
669 def __init__(self, test_runner): 681 def __init__(self, test_runner):
670 super(DromaeoSizeTest, self).__init__( 682 super(DromaeoSizeTest, self).__init__(
671 self.name(), 683 self.name(),
672 ['browser'], ['dart', 'frog_dom', 'frog_html', 'frog_htmlidiomatic'], 684 ['browser'], ['dart', 'frog_dom', 'frog_html', 'frog_htmlidiomatic'],
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 776
765 result = re.match(result_pattern, line.strip()) 777 result = re.match(result_pattern, line.strip())
766 if result: 778 if result:
767 variant = result.group(1) 779 variant = result.group(1)
768 metric = result.group(2) 780 metric = result.group(2)
769 num = result.group(3) 781 num = result.group(3)
770 if num.find('.') == -1: 782 if num.find('.') == -1:
771 num = int(num) 783 num = int(num)
772 else: 784 else:
773 num = float(num) 785 num = float(num)
774 self.report_results(metric, num, 'browser', variant, revision_num) 786 if self.test.test_runner.upload:
787 self.report_results(metric, num, 'browser', variant, revision_num,
788 self.CODE_SIZE)
775 789
776 f.close() 790 f.close()
777 791
778 792
779 class CompileTimeAndSizeTest(Test): 793 class CompileTimeAndSizeTest(Test):
780 """Run tests to determine how long minfrog takes to compile, and the compiled 794 """Run tests to determine how long frogc takes to compile, and the compiled
781 file output size of some benchmarking files.""" 795 file output size of some benchmarking files."""
782 def __init__(self, test_runner): 796 def __init__(self, test_runner):
783 """Reference to the test_runner object that notifies us when to begin 797 """Reference to the test_runner object that notifies us when to begin
784 testing.""" 798 testing."""
785 super(CompileTimeAndSizeTest, self).__init__( 799 super(CompileTimeAndSizeTest, self).__init__(
786 self.name(), ['commandline'], ['frog'], 800 self.name(), ['commandline'], ['frog'], ['swarm', 'total'],
787 ['Compiling on Dart VM', 'Bootstrapping', 'minfrog', 'swarm', 'total'],
788 test_runner, self.CompileTester(self), 801 test_runner, self.CompileTester(self),
789 self.CompileProcessor(self)) 802 self.CompileProcessor(self))
790 self.dart_compiler = os.path.join( 803 self.dart_compiler = os.path.join(
791 DART_INSTALL_LOCATION, utils.GetBuildRoot(utils.GuessOS(), 804 DART_INSTALL_LOCATION, utils.GetBuildRoot(utils.GuessOS(),
792 'release', 'ia32'), 'dart-sdk', 'bin', 'frogc') 805 'release', 'ia32'), 'dart-sdk', 'bin', 'frogc')
793 _suffix = '' 806 _suffix = ''
794 if platform.system() == 'Windows': 807 if platform.system() == 'Windows':
795 _suffix = '.exe' 808 _suffix = '.exe'
796 self.dart_vm = os.path.join( 809 self.dart_vm = os.path.join(
797 DART_INSTALL_LOCATION, utils.GetBuildRoot(utils.GuessOS(), 810 DART_INSTALL_LOCATION, utils.GetBuildRoot(utils.GuessOS(),
798 'release', 'ia32'), 'dart-sdk', 'bin','dart' + _suffix) 811 'release', 'ia32'), 'dart-sdk', 'bin','dart' + _suffix)
799 self.failure_threshold = { 812 self.failure_threshold = {'swarm' : 100, 'total' : 100}
800 'Compiling on Dart VM' : 1, 'Bootstrapping' : .5, 'minfrog' : 100,
801 'swarm' : 100, 'total' : 100}
802 813
803 @staticmethod 814 @staticmethod
804 def name(): 815 def name():
805 return 'time-size' 816 return 'time-size'
806 817
807 class CompileTester(Tester): 818 class CompileTester(Tester):
808 def run_tests(self): 819 def run_tests(self):
809 os.chdir('frog') 820 os.chdir('frog')
810 self.test.trace_file = os.path.join( 821 self.test.trace_file = os.path.join(
811 '..', 'tools', 'testing', 'perf_testing', 822 '..', 'tools', 'testing', 'perf_testing',
812 self.test.result_folder_name, 823 self.test.result_folder_name,
813 self.test.result_folder_name + self.test.cur_time) 824 self.test.result_folder_name + self.test.cur_time)
814 825
815 self.add_svn_revision_to_trace(self.test.trace_file) 826 self.add_svn_revision_to_trace(self.test.trace_file)
816 827
817 elapsed = self.test.test_runner.time_cmd(
818 [self.test.dart_vm, os.path.join('.', 'minfrogc.dart'),
819 '--out=minfrog', 'minfrog.dart'])
820 self.test.test_runner.run_cmd( 828 self.test.test_runner.run_cmd(
821 ['echo', '%f Compiling on Dart VM in production mode in seconds' 829 [self.test.dart_vm, 'frogc.dart', '--out=swarm-result',
822 % elapsed], self.test.trace_file, append=True)
823 elapsed = self.test.test_runner.time_cmd(
824 [os.path.join('.', 'minfrog'), '--out=minfrog', 'minfrog.dart',
825 os.path.join('tests', 'hello.dart')])
826 if elapsed < self.test.failure_threshold['Bootstrapping']:
827 #minfrog didn't compile correctly. Stop testing now, because subsequent
828 #numbers will be meaningless.
829 return
830 size = os.path.getsize('minfrog')
831 self.test.test_runner.run_cmd(
832 ['echo', '%f Bootstrapping time in seconds in production mode' %
833 elapsed], self.test.trace_file, append=True)
834 self.test.test_runner.run_cmd(
835 ['echo', '%d Generated checked minfrog size' % size],
836 self.test.trace_file, append=True)
837
838 self.test.test_runner.run_cmd(
839 [self.test.dart_compiler, '--out=swarm-result',
840 os.path.join('..', 'samples', 'swarm', 830 os.path.join('..', 'samples', 'swarm',
841 'swarm.dart')]) 831 'swarm.dart')])
842 832
843 swarm_size = 0 833 swarm_size = 0
844 try: 834 try:
845 swarm_size = os.path.getsize('swarm-result') 835 swarm_size = os.path.getsize('swarm-result')
846 except OSError: 836 except OSError:
847 pass #If compilation failed, continue on running other tests. 837 pass #If compilation failed, continue on running other tests.
848 838
849 self.test.test_runner.run_cmd( 839 self.test.test_runner.run_cmd(
850 [self.test.dart_compiler, '--out=total-result', 840 [self.test.dart_vm, 'frogc.dart', '--out=total-result',
851 os.path.join('..', 'samples', 'total', 841 os.path.join('..', 'samples', 'total',
852 'client', 'Total.dart')]) 842 'client', 'Total.dart')])
853 total_size = 0 843 total_size = 0
854 try: 844 try:
855 total_size = os.path.getsize('total-result') 845 total_size = os.path.getsize('total-result')
856 except OSError: 846 except OSError:
857 pass #If compilation failed, continue on running other tests. 847 pass #If compilation failed, continue on running other tests.
858 848
859 self.test.test_runner.run_cmd( 849 self.test.test_runner.run_cmd(
860 ['echo', '%d Generated checked swarm size' % swarm_size], 850 ['echo', '%d Generated checked swarm size' % swarm_size],
861 self.test.trace_file, append=True) 851 self.test.trace_file, append=True)
862 852
863 self.test.test_runner.run_cmd( 853 self.test.test_runner.run_cmd(
864 ['echo', '%d Generated checked total size' % total_size], 854 ['echo', '%d Generated checked total size' % total_size],
865 self.test.trace_file, append=True) 855 self.test.trace_file, append=True)
866 856
867 #Revert our newly built minfrog to prevent conflicts when we update
868 self.test.test_runner.run_cmd(
869 ['svn', 'revert', os.path.join(os.getcwd(), 'minfrog')])
870 os.chdir('..') 857 os.chdir('..')
871 858
872 859
873 class CompileProcessor(Processor): 860 class CompileProcessor(Processor):
874 861
875 def process_file(self, afile): 862 def process_file(self, afile):
876 """Pull all the relevant information out of a given tracefile. 863 """Pull all the relevant information out of a given tracefile.
877 864
878 Args: 865 Args:
879 afile: is the filename string we will be processing.""" 866 afile: is the filename string we will be processing."""
880 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 867 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools',
881 'testing', 'perf_testing')) 868 'testing', 'perf_testing'))
882 f = open(os.path.join(self.test.result_folder_name, afile)) 869 f = open(os.path.join(self.test.result_folder_name, afile))
883 tabulate_data = False 870 tabulate_data = False
884 revision_num = 0 871 revision_num = 0
885 for line in f.readlines(): 872 for line in f.readlines():
886 tokens = line.split() 873 tokens = line.split()
887 if 'Revision' in line: 874 if 'Revision' in line:
888 revision_num = int(line.split()[1]) 875 revision_num = int(line.split()[1])
889 else: 876 else:
890 for metric in self.test.values_list: 877 for metric in self.test.values_list:
891 if metric in line: 878 if metric in line:
892 num = tokens[0] 879 num = tokens[0]
893 if num.find('.') == -1: 880 if num.find('.') == -1:
894 num = int(num) 881 num = int(num)
895 else: 882 else:
896 num = float(num) 883 num = float(num)
897 self.report_results(metric, num, 'commandline', 'frog', 884 score_type = self.CODE_SIZE
898 revision_num) 885 if 'Compiling' in metric or 'Bootstrapping' in metric:
886 score_type = self.COMPILE_TIME
887 if self.test.test_runner.upload:
888 self.report_results(metric, num, 'commandline', 'frog',
889 revision_num, score_type)
ricow1 2012/04/25 08:42:18 indentation off
899 890
900 f.close() 891 f.close()
901 892
902 893
903 class TestBuilder(object): 894 class TestBuilder(object):
904 """Construct the desired test object.""" 895 """Construct the desired test object."""
905 available_suites = dict((suite.name(), suite) for suite in [ 896 available_suites = dict((suite.name(), suite) for suite in [
906 CompileTimeAndSizeTest, CommonBrowserTest, DromaeoTest, DromaeoSizeTest]) 897 CompileTimeAndSizeTest, CommonBrowserTest, DromaeoTest, DromaeoSizeTest])
907 898
908 @staticmethod 899 @staticmethod
(...skipping 12 matching lines...) Expand all
921 while True: 912 while True:
922 if runner.has_new_code(): 913 if runner.has_new_code():
923 runner.run_test_sequence() 914 runner.run_test_sequence()
924 else: 915 else:
925 time.sleep(200) 916 time.sleep(200)
926 else: 917 else:
927 runner.run_test_sequence() 918 runner.run_test_sequence()
928 919
929 if __name__ == '__main__': 920 if __name__ == '__main__':
930 main() 921 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