Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 math | 8 import math |
| 9 from matplotlib.font_manager import FontProperties | 9 try: |
| 10 import matplotlib.pyplot as plt | 10 from matplotlib.font_manager import FontProperties |
| 11 import matplotlib.pyplot as plt | |
| 12 except ImportError: | |
| 13 print 'Warning: no matplotlib. ' + \ | |
| 14 'Please ignore if you are running buildbot smoketests.' | |
| 15 import optparse | |
| 11 import os | 16 import os |
| 12 import platform | 17 import platform |
| 13 import shutil | 18 import shutil |
| 14 import subprocess | 19 import subprocess |
| 15 import time | 20 import time |
| 16 import traceback | 21 import traceback |
| 17 | 22 |
| 18 """This script runs to track performance and correctness progress of | 23 """This script runs to track performance and correctness progress of |
| 19 different svn revisions. It tests to see if there a newer version of the code on | 24 different svn revisions. It tests to see if there a newer version of the code on |
| 20 the server, and will sync and run the performance tests if so.""" | 25 the server, and will sync and run the performance tests if so.""" |
| 21 | 26 |
| 22 DART_INSTALL_LOCATION = os.path.join(os.path.dirname(os.path.abspath(__file__)), | 27 DART_INSTALL_LOCATION = os.path.join(os.path.dirname(os.path.abspath(__file__)), |
| 23 '..', '..', '..') | 28 '..', '..', '..') |
| 24 V8_MEAN = 'V8 Mean' | 29 V8_MEAN = 'V8 Mean' |
| 25 FROG_MEAN = 'frog Mean' | 30 FROG_MEAN = 'frog Mean' |
| 26 COMMAND_LINE = 'commandline' | 31 COMMAND_LINE = 'commandline' |
| 27 V8 = 'v8' | 32 V8 = 'v8' |
| 28 FROG = 'frog' | 33 FROG = 'frog' |
| 29 V8_AND_FROG = [V8, FROG] | 34 V8_AND_FROG = [V8, FROG] |
| 30 CORRECTNESS = 'Percent passing' | 35 CORRECTNESS = 'Percent passing' |
| 31 BENCHMARKS = ['Mandelbrot', 'DeltaBlue', 'Richards', 'NBody', | 36 BENCHMARKS = ['Mandelbrot', 'DeltaBlue', 'Richards', 'NBody', |
| 32 'BinaryTrees', 'Fannkuch', 'Meteor', 'BubbleSort', 'Fibonacci', | 37 'BinaryTrees', 'Fannkuch', 'Meteor', 'BubbleSort', 'Fibonacci', |
| 33 'Loop', 'Permute', 'Queens', 'QuickSort', 'Recurse', 'Sieve', 'Sum', | 38 'Loop', 'Permute', 'Queens', 'QuickSort', 'Recurse', 'Sieve', 'Sum', |
| 34 'Tak', 'Takl', 'Towers', 'TreeSort'] | 39 'Tak', 'Takl', 'Towers', 'TreeSort'] |
| 35 COLORS = ['blue', 'green', 'red', 'cyan', 'magenta', 'black'] | 40 COLORS = ['blue', 'green', 'red', 'cyan', 'magenta', 'black'] |
| 36 GRAPH_OUT_DIR = 'graphs' | 41 GRAPH_OUT_DIR = 'graphs' |
| 42 SLEEP_TIME = 200 | |
| 43 PERFBOT_MODE = False | |
| 37 | 44 |
| 38 """First, some utility methods.""" | 45 """First, some utility methods.""" |
| 39 | 46 |
| 40 def RunCmd(string): | 47 def RunCmd(cmd_list, outfile=None, append=False): |
| 41 """Run the specified command and print out any output to stdout. | 48 """Run the specified command and print out any output to stdout. |
| 42 Args: | 49 Args: |
| 43 string the command to run""" | 50 cmd_list a list of strings that make up the command to run |
| 44 p = subprocess.Popen(string, stdout = subprocess.PIPE, | 51 outfile a string indicating the name of the file that we should write stdout |
| 45 stderr = subprocess.STDOUT, close_fds=True) | 52 to |
| 53 append True if we want to append to the file instead of overwriting it""" | |
| 54 print cmd_list | |
|
Siggi Cherem (dart-lang)
2011/12/02 21:33:43
for later - we could only print if you specify --v
| |
| 55 out = subprocess.PIPE | |
| 56 if outfile: | |
| 57 mode = 'w' | |
| 58 if append: | |
| 59 mode = 'a' | |
| 60 out = open(outfile, mode) | |
| 61 p = subprocess.Popen(cmd_list, stdout = out, | |
| 62 stderr = subprocess.PIPE, close_fds=True) | |
| 46 output, not_used = p.communicate(); | 63 output, not_used = p.communicate(); |
| 47 print output: | 64 if output: |
| 48 return lines | 65 print output |
| 66 return output | |
| 49 | 67 |
| 50 def TimeCmd(self, cmd): | 68 def TimeCmd(cmd): |
| 69 """Determine the amount of (real) time it takes to execute a given command.""" | |
| 51 start = time.time() | 70 start = time.time() |
| 52 RunCmd(cmd) | 71 RunCmd(cmd) |
| 53 return time.time() - start | 72 return time.time() - start |
| 54 | 73 |
| 55 def SyncAndBuild(failed_once=False): | 74 def SyncAndBuild(failed_once=False): |
| 56 """Make sure we have the latest version of of the repo, and build it. We | 75 """Make sure we have the latest version of of the repo, and build it. We |
| 57 begin and end standing in DART_INSTALL_LOCATION. | 76 begin and end standing in DART_INSTALL_LOCATION. |
| 58 Args: | 77 Args: |
| 59 failed_once True if we have attempted to build this once before, and we've | 78 failed_once True if we have attempted to build this once before, and we've |
| 60 failed, indicating .""" | 79 failed, indicating the build is broken.""" |
| 61 os.chdir(DART_INSTALL_LOCATION) | 80 os.chdir(DART_INSTALL_LOCATION) |
| 62 #Revert our newly built frogsh to prevent conflicts when we update | 81 #Revert our newly built frogsh to prevent conflicts when we update |
| 63 RunCmd('svn revert ' + os.path.join(os.getcwd(), 'frog', 'frogsh')) | 82 RunCmd(['svn', 'revert', os.path.join(os.getcwd(), 'frog', 'frogsh')]) |
| 64 | 83 |
| 65 RunCmd('gclient sync') | 84 RunCmd(['gclient', 'sync']) |
| 66 lines = RunCmd('%s -m release' % os.path.join('.', 'tools', 'build.py')) | 85 lines = RunCmd([os.path.join('.', 'tools', 'build.py'), '-m', 'release']) |
| 67 os.chdir('frog') | 86 os.chdir('frog') |
| 68 lines += RunCmd('%s -m debug,release' % os.path.join('..', 'tools', | 87 lines += RunCmd([os.path.join('..', 'tools', 'build.py'), '-m', |
| 69 'build.py')) | 88 'debug,release']) |
| 70 os.chdir('..') | 89 os.chdir('..') |
| 71 | 90 |
| 72 for line in lines: | 91 for line in lines: |
| 73 if '** BUILD FAILED **' in lines: | 92 if 'BUILD FAILED' in lines: |
| 74 if TestRunner.failed_once: | 93 if failed_once: |
| 75 # Someone checked in a broken build! Just stop trying to make it work | 94 # Someone checked in a broken build! Just stop trying to make it work |
| 76 # and wait for the next hour to try again. | 95 # and wait for the next hour to try again. |
| 77 print 'Broken Build' | 96 print 'Broken Build' |
| 78 sys.exit(0) | 97 sys.exit(0) |
| 79 #Remove the xcode directory and attempt to build again. If it still | 98 #Remove the xcode directory and attempt to build again. If it still |
| 80 #fails, abort, and try again next hour. | 99 #fails, abort, and try again next hour. |
| 81 out_dir = 'out' | 100 out_dir = 'out' |
| 82 if platform.system() == 'Darwin': | 101 if platform.system() == 'Darwin': |
| 83 out_dir = 'xcodebuild' | 102 out_dir = 'xcodebuild' |
| 84 os.removedirs(os.getcwd() + os.path.join('dart', out_dir, 'Release_ia32')) | 103 shutil.rmtree(os.path.join(os.getcwd(), out_dir, 'Release_ia32')) |
| 85 os.removedirs(os.getcwd() + os.path.join('dart', 'frog', out_dir, | 104 shutil.rmtree(os.path.join(os.getcwd(), 'frog', out_dir, |
| 105 'Debug_ia32')) | |
| 106 shutil.rmtree(os.path.join(os.getcwd(), 'frog', out_dir, | |
| 86 'Release_ia32')) | 107 'Release_ia32')) |
| 87 os.removedirs(os.getcwd() + os.path.join('dart', 'frog', out_dir, | 108 SyncAndBuild(True) |
| 88 'Debug_ia32')) | |
| 89 TestRunner.failed_once = True | |
| 90 SyncAndBuild() | |
| 91 | 109 |
| 92 def EnsureOutputDirectory(dir_name): | 110 def EnsureOutputDirectory(dir_name): |
| 93 """Test that the listed directory name exists, and if not, create one for | 111 """Test that the listed directory name exists, and if not, create one for |
| 94 our output to be placed.""" | 112 our output to be placed. |
| 113 Args: | |
| 114 dir_name the directory we will create if it does not exist.""" | |
| 95 dir_path = os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing', | 115 dir_path = os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing', |
| 96 'perf_testing', dir_name) | 116 'perf_testing', dir_name) |
| 97 if not os.path.exists(dir_path): | 117 if not os.path.exists(dir_path): |
| 98 os.mkdir(dir_path) | 118 os.mkdir(dir_path) |
| 99 print 'Creating output directory ', dir_path | 119 print 'Creating output directory ', dir_path |
| 100 | 120 |
| 101 def HasNewCode(): | 121 def HasNewCode(): |
| 102 """Tests if there are any newer versions of files on the server.""" | 122 """Tests if there are any newer versions of files on the server.""" |
| 103 os.chdir(DART_INSTALL_LOCATION) | 123 os.chdir(DART_INSTALL_LOCATION) |
| 104 results = RunCmd('svn st -u') | 124 results = RunCmd(['svn', 'st', '-u']) |
| 105 for line in results: | 125 for line in results: |
| 106 if '*' in line: | 126 if '*' in line: |
| 107 return True | 127 return True |
| 108 return False | 128 return False |
| 109 | 129 |
| 110 def GetBrowsers(): | 130 def GetBrowsers(): |
| 131 if not PERFBOT_MODE: | |
| 132 # Only Firefox (and Chrome, but we have Dump Render Tree) works in Linux | |
| 133 return ['ff'] | |
| 111 browsers = ['ff', 'chrome'] | 134 browsers = ['ff', 'chrome'] |
| 112 if platform.system() == 'Windows': | 135 if platform.system() == 'Windows': |
| 113 browsers += ['ie'] | 136 browsers += ['ie'] |
| 114 return browsers | 137 return browsers |
| 115 | 138 |
| 139 def GetVersions(): | |
| 140 if not PERBOT_MODE: | |
| 141 return [FROG] | |
| 142 else: | |
| 143 return V8_AND_FROG | |
| 144 | |
| 116 class TestRunner(object): | 145 class TestRunner(object): |
| 117 """The base clas to provide shared code for different tests we will run and | 146 """The base clas to provide shared code for different tests we will run and |
| 118 graph.""" | 147 graph.""" |
| 119 | 148 |
| 120 def __init__(self, result_folder_name, platform_list, v8_and_or_frog_list, | 149 def __init__(self, result_folder_name, platform_list, v8_and_or_frog_list, |
| 121 values_list): | 150 values_list): |
| 122 """Args: | 151 """Args: |
| 123 result_folder_name the name of the folder where a tracefile of | 152 result_folder_name the name of the folder where a tracefile of |
| 124 performance results will be stored. | 153 performance results will be stored. |
| 125 platform_list a list containing the platform(s) that our data has been | 154 platform_list a list containing the platform(s) that our data has been |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 191 fontP = FontProperties() | 220 fontP = FontProperties() |
| 192 fontP.set_size('small') | 221 fontP.set_size('small') |
| 193 plt.legend(loc=legend_loc, prop = fontP) | 222 plt.legend(loc=legend_loc, prop = fontP) |
| 194 | 223 |
| 195 fig = plt.gcf() | 224 fig = plt.gcf() |
| 196 fig.set_size_inches(size_x, size_y) | 225 fig.set_size_inches(size_x, size_y) |
| 197 fig.savefig(os.path.join(GRAPH_OUT_DIR, filename)) | 226 fig.savefig(os.path.join(GRAPH_OUT_DIR, filename)) |
| 198 | 227 |
| 199 def AddSvnRevisionToTrace(self, outfile): | 228 def AddSvnRevisionToTrace(self, outfile): |
| 200 """Add the svn version number to the provided tracefile.""" | 229 """Add the svn version number to the provided tracefile.""" |
| 201 p = subprocess.Popen('svn info ', stdout = subprocess.PIPE, | 230 p = subprocess.Popen(['svn', 'info'], stdout = subprocess.PIPE, |
| 202 stderr = subprocess.STDOUT, close_fds=True) | 231 stderr = subprocess.STDOUT, close_fds=True) |
| 203 output, not_used = p.communicate() | 232 output, not_used = p.communicate() |
| 204 for line in output.split('\n'): | 233 for line in output.split('\n'): |
| 205 if 'Revision' in line: | 234 if 'Revision' in line: |
| 206 RunCmd('echo "%s" > %s' % (line.strip(), outfile)) | 235 RunCmd(['echo', line.strip()], outfile) |
| 207 | 236 |
| 208 def WriteHtml(self, delimiter, rev_nums, label_1, dict_1, label_2, dict_2, | 237 def WriteHtml(self, delimiter, rev_nums, label_1, dict_1, label_2, dict_2, |
| 209 cleanFile=False): | 238 cleanFile=False): |
| 210 """Adds an html table to the webpage to display the data values. This method | 239 """Adds an html table to the webpage to display the data values. This method |
| 211 will be removed when we have a nicer way to display data values.""" | 240 will be removed when we have a nicer way to display data values.""" |
| 212 #TODO(efortuna): fix this. | 241 #TODO(efortuna): fix this. |
| 213 return | 242 return |
| 214 #TODO(efortuna): Take this method out when have finalized where the data is | 243 #TODO(efortuna): Take this method out when have finalized where the data is |
| 215 # going to be displayed. | 244 # going to be displayed. |
| 216 f = '' | 245 f = '' |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 247 geo_mean += math.log(self.values_dict[platform][frog_or_v8][benchmark][ | 276 geo_mean += math.log(self.values_dict[platform][frog_or_v8][benchmark][ |
| 248 len(self.values_dict[platform][frog_or_v8][benchmark]) - 1]) | 277 len(self.values_dict[platform][frog_or_v8][benchmark]) - 1]) |
| 249 | 278 |
| 250 mean = V8_MEAN | 279 mean = V8_MEAN |
| 251 if frog_or_v8 == FROG: | 280 if frog_or_v8 == FROG: |
| 252 mean = FROG_MEAN | 281 mean = FROG_MEAN |
| 253 self.values_dict[platform][frog_or_v8][mean] += \ | 282 self.values_dict[platform][frog_or_v8][mean] += \ |
| 254 [math.pow(math.e, geo_mean / len(BENCHMARKS))] | 283 [math.pow(math.e, geo_mean / len(BENCHMARKS))] |
| 255 self.revision_dict[platform][frog_or_v8][mean] += [svn_revision] | 284 self.revision_dict[platform][frog_or_v8][mean] += [svn_revision] |
| 256 | 285 |
| 286 def Cleanup(self): | |
| 287 pass | |
| 288 | |
| 257 def Run(self): | 289 def Run(self): |
| 258 """Run the benchmarks/tests from the command line and plot the | 290 """Run the benchmarks/tests from the command line and plot the |
| 259 results.""" | 291 results.""" |
| 260 plt.cla() # cla = clear current axes | 292 plt.cla() # cla = clear current axes |
| 261 os.chdir(DART_INSTALL_LOCATION) | 293 os.chdir(DART_INSTALL_LOCATION) |
| 262 EnsureOutputDirectory(self.result_folder_name) | 294 EnsureOutputDirectory(self.result_folder_name) |
| 263 EnsureOutputDirectory(GRAPH_OUT_DIR) | 295 EnsureOutputDirectory(GRAPH_OUT_DIR) |
| 264 self.RunTests() | 296 self.RunTests() |
| 265 os.chdir(os.path.join('tools', 'testing', 'perf_testing')) | 297 os.chdir(os.path.join('tools', 'testing', 'perf_testing')) |
| 266 | 298 |
| 267 # TODO(efortuna): You will want to make this only use a subset of the files | 299 # TODO(efortuna): You will want to make this only use a subset of the files |
| 268 # eventually. | 300 # eventually. |
| 269 files = os.listdir(self.result_folder_name) | 301 files = os.listdir(self.result_folder_name) |
| 270 | 302 |
| 271 for afile in files: | 303 for afile in files: |
| 272 if not afile.startswith('.'): | 304 if not afile.startswith('.'): |
| 273 self.ProcessFile(afile) | 305 self.ProcessFile(afile) |
| 274 self.PlotResults('%s.png' % self.result_folder_name) | 306 |
| 307 if PERFBOT_MODE: | |
| 308 self.PlotResults('%s.png' % self.result_folder_name) | |
| 309 self.Cleanup(); | |
| 275 | 310 |
| 276 class PerformanceTestRunner(TestRunner): | 311 class PerformanceTestRunner(TestRunner): |
| 277 """Super class for all performance testing.""" | 312 """Super class for all performance testing.""" |
| 278 def __init__(self, result_folder_name, platform_list, platform_type): | 313 def __init__(self, result_folder_name, platform_list, platform_type): |
| 279 super(PerformanceTestRunner, self).__init__(result_folder_name, | 314 super(PerformanceTestRunner, self).__init__(result_folder_name, |
| 280 platform_list, V8_AND_FROG, BENCHMARKS) | 315 platform_list, GetVersions(), BENCHMARKS) |
| 281 self.platform_list = platform_list | 316 self.platform_list = platform_list |
| 282 self.platform_type = platform_type | 317 self.platform_type = platform_type |
| 283 | 318 |
| 284 def PlotAllPerf(self, png_filename): | 319 def PlotAllPerf(self, png_filename): |
| 285 """Create a plot that shows the performance changes of individual benchmarks | 320 """Create a plot that shows the performance changes of individual benchmarks |
| 286 run by V8 and generated by frog, over svn history.""" | 321 run by V8 and generated by frog, over svn history.""" |
| 287 for benchmark in BENCHMARKS: | 322 for benchmark in BENCHMARKS: |
| 288 self.StyleAndSavePerfPlot( | 323 self.StyleAndSavePerfPlot( |
| 289 'Performance of %s over time on the %s' % (benchmark, | 324 'Performance of %s over time on the %s' % (benchmark, |
| 290 self.platform_type), 'Speed (bigger = better)', 16, 14, 'lower left', | 325 self.platform_type), 'Speed (bigger = better)', 16, 14, 'lower left', |
| 291 benchmark + png_filename, self.platform_list, V8_AND_FROG, | 326 benchmark + png_filename, self.platform_list, GetVersions(), |
| 292 [benchmark]) | 327 [benchmark]) |
| 293 | 328 |
| 294 def PlotAvgPerf(self, png_filename): | 329 def PlotAvgPerf(self, png_filename): |
| 295 """Generate a plot that shows the performance changes of the geomentric mean | 330 """Generate a plot that shows the performance changes of the geomentric mean |
| 296 of V8 and frog benchmark performance over svn history.""" | 331 of V8 and frog benchmark performance over svn history.""" |
| 297 (title, y_axis, size_x, size_y, loc, filename) = \ | 332 (title, y_axis, size_x, size_y, loc, filename) = \ |
| 298 ('Geometric Mean of benchmark %s performance' % self.platform_type, | 333 ('Geometric Mean of benchmark %s performance' % self.platform_type, |
| 299 'Speed (bigger = better)', 16, 5, 'center', 'avg'+png_filename) | 334 'Speed (bigger = better)', 16, 5, 'center', 'avg'+png_filename) |
| 300 for platform in self.platform_list: | 335 for platform in self.platform_list: |
| 301 self.StyleAndSavePerfPlot(title, y_axis, size_x, size_y, loc, filename, | 336 self.StyleAndSavePerfPlot(title, y_axis, size_x, size_y, loc, filename, |
| 302 [platform], [V8], [V8_MEAN], True) | 337 [platform], [V8], [V8_MEAN], True) |
| 303 self.StyleAndSavePerfPlot(title, y_axis, size_x, size_y, loc, filename, | 338 self.StyleAndSavePerfPlot(title, y_axis, size_x, size_y, loc, filename, |
| 304 [platform], [FROG], [FROG_MEAN], False) | 339 [platform], [FROG], [FROG_MEAN], False) |
| 305 self.WriteHtml('table', | 340 self.WriteHtml('table', |
| 306 self.revision_dict[platform][V8], | 341 self.revision_dict[platform][V8], |
| 307 'V8 mean', self.values_dict[platform][V8][V8_MEAN], | 342 'V8 mean', self.values_dict[platform][V8][V8_MEAN], |
| 308 'Frog mean', self.values_dict[platform][FROG][FROG_MEAN], | 343 'Frog mean', self.values_dict[platform][FROG][FROG_MEAN], |
| 309 True) | 344 True) |
| 310 | 345 |
| 311 def PlotResults(self, png_filename): | 346 def PlotResults(self, png_filename): |
| 312 self.PlotAllPerf(png_filename) | 347 self.PlotAllPerf(png_filename) |
| 313 self.PlotAvgPerf('2' + png_filename) | 348 self.PlotAvgPerf('2' + png_filename) |
| 314 | 349 |
| 350 | |
| 315 class CommandLinePerformanceTestRunner(PerformanceTestRunner): | 351 class CommandLinePerformanceTestRunner(PerformanceTestRunner): |
| 316 """Run performance tests from the command line.""" | 352 """Run performance tests from the command line.""" |
| 317 | 353 |
| 318 def __init__(self, result_folder_name): | 354 def __init__(self, result_folder_name): |
| 319 super(CommandLinePerformanceTestRunner, self).__init__(result_folder_name, | 355 super(CommandLinePerformanceTestRunner, self).__init__(result_folder_name, |
| 320 [COMMAND_LINE], 'command line') | 356 [COMMAND_LINE], 'command line') |
| 321 | 357 |
| 322 def ProcessFile(self, afile): | 358 def ProcessFile(self, afile): |
| 323 """Pull all the relevant information out of a given tracefile. | 359 """Pull all the relevant information out of a given tracefile. |
| 324 | 360 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 349 self.revision_dict[COMMAND_LINE][FROG][benchmark] += [revision_num] | 385 self.revision_dict[COMMAND_LINE][FROG][benchmark] += [revision_num] |
| 350 self.values_dict[COMMAND_LINE][FROG][benchmark] += [frog_value] | 386 self.values_dict[COMMAND_LINE][FROG][benchmark] += [frog_value] |
| 351 f.close() | 387 f.close() |
| 352 | 388 |
| 353 self.CalculateGeometricMean(COMMAND_LINE, FROG, revision_num) | 389 self.CalculateGeometricMean(COMMAND_LINE, FROG, revision_num) |
| 354 self.CalculateGeometricMean(COMMAND_LINE, V8, revision_num) | 390 self.CalculateGeometricMean(COMMAND_LINE, V8, revision_num) |
| 355 | 391 |
| 356 def RunTests(self): | 392 def RunTests(self): |
| 357 """Run a performance test on our updated system.""" | 393 """Run a performance test on our updated system.""" |
| 358 os.chdir('frog') | 394 os.chdir('frog') |
| 359 file_path = os.path.join('..', 'tools', 'testing', 'perf_testing', | 395 self.trace_file = os.path.join('..', 'tools', 'testing', 'perf_testing', |
| 360 self.result_folder_name, 'result') | 396 self.result_folder_name, 'result' + self.cur_time) |
| 361 RunCmd('python %s > %s%s' % (os.path.join('benchmarks', | 397 RunCmd(['python', os.path.join('benchmarks', 'perf_tests.py')], |
| 362 'perf_tests.py'), file_path, self.cur_time)) | 398 self.trace_file) |
| 363 os.chdir('..') | 399 os.chdir('..') |
| 364 | 400 |
| 365 | 401 |
| 366 class BrowserPerformanceTestRunner(PerformanceTestRunner): | 402 class BrowserPerformanceTestRunner(PerformanceTestRunner): |
| 367 """Runs performance tests, in the browser.""" | 403 """Runs performance tests, in the browser.""" |
| 368 | 404 |
| 369 def __init__(self, result_folder_name): | 405 def __init__(self, result_folder_name): |
| 370 super(BrowserPerformanceTestRunner, self).__init__( | 406 super(BrowserPerformanceTestRunner, self).__init__( |
| 371 result_folder_name, GetBrowsers(), 'browser') | 407 result_folder_name, GetBrowsers(), 'browser') |
| 372 | 408 |
| 373 def RunTests(self): | 409 def RunTests(self): |
| 374 """Run a performance test in the browser.""" | 410 """Run a performance test in the browser.""" |
| 375 os.chdir('frog') | 411 os.chdir('frog') |
| 376 RunCmd('python benchmarks/make_web_benchmarks.py') | 412 RunCmd(['python', os.path.join('benchmarks', 'make_web_benchmarks.py')]) |
| 377 os.chdir('..') | 413 os.chdir('..') |
| 378 | 414 |
| 379 for browser in GetBrowsers(): | 415 for browser in GetBrowsers(): |
| 380 for version in V8_AND_FROG: | 416 for version in GetVersions(): |
| 381 self.AddSvnRevisionToTrace(os.path.join('tools', 'testing', | 417 self.trace_file = os.path.join('tools', 'testing', 'perf_testing', |
| 382 'perf_testing', self.result_folder_name, | 418 self.result_folder_name, |
| 383 'perf-%s-%s-%s' % (self.cur_time, browser, version))) | 419 'perf-%s-%s-%s' % (self.cur_time, browser, version)) |
| 384 RunCmd('python %s --out %s --browser %s --timeout 1000 --perf >> %s' % | 420 self.AddSvnRevisionToTrace(self.trace_file) |
| 385 (os.path.join('tools', 'testing', 'run_selenium.py'), | 421 RunCmd(['python', os.path.join('tools', 'testing', 'run_selenium.py'), |
| 386 os.path.join(os.getcwd(), 'internal', 'browserBenchmarks', | 422 '--out', os.path.join(os.getcwd(), 'internal', 'browserBenchmarks', |
| 387 'benchmark_page_%s.html' % version), | 423 'benchmark_page_%s.html' % version), '--browser', browser, |
| 388 browser, | 424 '--timeout', '600', '--perf'], self.trace_file, append=True) |
| 389 os.path.join('tools', 'testing', 'perf_testing', | |
| 390 self.result_folder_name, 'perf-%s-%s-%s' % (self.cur_time, browser, | |
| 391 version)))) | |
| 392 | 425 |
| 393 def ProcessFile(self, afile): | 426 def ProcessFile(self, afile): |
| 394 """Comb through the html to find the performance results.""" | 427 """Comb through the html to find the performance results.""" |
| 395 parts = afile.split('-') | 428 parts = afile.split('-') |
| 396 browser = parts[2] | 429 browser = parts[2] |
| 397 version = parts[3] | 430 version = parts[3] |
| 398 f = open(os.path.join(self.result_folder_name, afile)) | 431 f = open(os.path.join(self.result_folder_name, afile)) |
| 399 lines = f.readlines() | 432 lines = f.readlines() |
| 400 line = '' | 433 line = '' |
| 401 i = 0 | 434 i = 0 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 431 self.revision_dict[browser][version][name] += [revision_num] | 464 self.revision_dict[browser][version][name] += [revision_num] |
| 432 | 465 |
| 433 f.close() | 466 f.close() |
| 434 self.CalculateGeometricMean(browser, version, revision_num) | 467 self.CalculateGeometricMean(browser, version, revision_num) |
| 435 | 468 |
| 436 def WriteHtml(self, delimiter, rev_nums, label_1, dict_1, label_2, dict_2, | 469 def WriteHtml(self, delimiter, rev_nums, label_1, dict_1, label_2, dict_2, |
| 437 cleanFile=False): | 470 cleanFile=False): |
| 438 #TODO(efortuna) | 471 #TODO(efortuna) |
| 439 pass | 472 pass |
| 440 | 473 |
| 474 | |
| 475 def Cleanup(): | |
| 476 # Kill the zombie chromedriver processes. | |
| 477 RunCmd(['killall', 'chromedriver']) | |
| 478 | |
| 479 | |
| 441 class BrowserCorrectnessTestRunner(TestRunner): | 480 class BrowserCorrectnessTestRunner(TestRunner): |
| 442 def __init__(self, test_type, result_folder_name): | 481 def __init__(self, test_type, result_folder_name): |
| 443 super(BrowserCorrectnessTestRunner, self).__init__(result_folder_name, | 482 super(BrowserCorrectnessTestRunner, self).__init__(result_folder_name, |
| 444 GetBrowsers(), [FROG], [CORRECTNESS]) | 483 GetBrowsers(), [FROG], [CORRECTNESS]) |
| 445 self.test_type = test_type | 484 self.test_type = test_type |
| 446 | 485 |
| 447 def RunTests(self): | 486 def RunTests(self): |
| 448 """Run a test of the latest svn revision.""" | 487 """Run a test of the latest svn revision.""" |
| 449 for browser in GetBrowsers(): | 488 for browser in GetBrowsers(): |
| 450 current_file = 'correctness%s-%s' % (self.cur_time, browser) | 489 current_file = 'correctness%s-%s' % (self.cur_time, browser) |
| 451 current_file_path = os.path.join('tools', 'testing', | 490 self.trace_file = os.path.join('tools', 'testing', |
| 452 'perf_testing', self.result_folder_name, current_file) | 491 'perf_testing', self.result_folder_name, current_file) |
| 453 self.AddSvnRevisionToTrace(current_file_path) | 492 self.AddSvnRevisionToTrace(self.trace_file) |
| 454 RunCmd(os.path.join('.', 'tools', 'test.py') + | 493 RunCmd([os.path.join('.', 'tools', 'test.py'), |
| 455 ' --component=webdriver --flag=%s --report --timeout=20 ' % browser + | 494 '--component=webdriver', '--flag=%s' % browser, '--report', |
| 456 '--progress=color --mode=release -j1 %s >>' % self.test_type + | 495 '--timeout=20', '--progress=color', '--mode=release', '-j1', |
| 457 current_file_path) | 496 self.test_type], self.trace_file, append=True) |
| 458 | 497 |
| 459 def ProcessFile(self, afile): | 498 def ProcessFile(self, afile): |
| 460 """Given a trace file, extract all the relevant information out of it to | 499 """Given a trace file, extract all the relevant information out of it to |
| 461 determine the number of correctly passing tests. | 500 determine the number of correctly passing tests. |
| 462 | 501 |
| 463 Arguments: | 502 Arguments: |
| 464 afile the filename string""" | 503 afile the filename string""" |
| 465 browser = afile.rpartition('-')[2] | 504 browser = afile.rpartition('-')[2] |
| 466 f = open(os.path.join(self.result_folder_name, afile)) | 505 f = open(os.path.join(self.result_folder_name, afile)) |
| 467 revision_num = 0 | 506 revision_num = 0 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 489 f.close() | 528 f.close() |
| 490 | 529 |
| 491 def PlotResults(self, png_filename): | 530 def PlotResults(self, png_filename): |
| 492 first_time = True | 531 first_time = True |
| 493 for browser in GetBrowsers(): | 532 for browser in GetBrowsers(): |
| 494 self.StyleAndSavePerfPlot('Percentage of language tests passing in ' | 533 self.StyleAndSavePerfPlot('Percentage of language tests passing in ' |
| 495 'different browsers', '% of tests passed', 8, 8, 'lower left', | 534 'different browsers', '% of tests passed', 8, 8, 'lower left', |
| 496 png_filename, [browser], [FROG], [CORRECTNESS], first_time) | 535 png_filename, [browser], [FROG], [CORRECTNESS], first_time) |
| 497 first_time = False | 536 first_time = False |
| 498 | 537 |
| 538 def Cleanup(): | |
| 539 # Kill the zombie chromedriver processes. | |
| 540 RunCmd(['killall', 'chromedriver']) | |
| 499 | 541 |
| 500 class CompileTimeAndSizeTestRunner(TestRunner): | 542 class CompileTimeAndSizeTestRunner(TestRunner): |
| 501 """Run tests to determine how long frogsh takes to compile, and the compiled | 543 """Run tests to determine how long frogsh takes to compile, and the compiled |
| 502 file output size of some benchmarking files.""" | 544 file output size of some benchmarking files.""" |
| 503 def __init__(self, result_folder_name): | 545 def __init__(self, result_folder_name): |
| 504 super(CompileTimeAndSizeTestRunner, self).__init__(result_folder_name, | 546 super(CompileTimeAndSizeTestRunner, self).__init__(result_folder_name, |
| 505 [COMMAND_LINE], [FROG], ['Compiling on Dart VM', 'Bootstrapping', | 547 [COMMAND_LINE], [FROG], ['Compiling on Dart VM', 'Bootstrapping', |
| 506 'frogsh', 'swarm', 'total']) | 548 'frogsh', 'swarm', 'total']) |
| 507 self.failure_threshold = {'Compiling on Dart VM' : 1, 'Bootstrapping' : .5, | 549 self.failure_threshold = {'Compiling on Dart VM' : 1, 'Bootstrapping' : .5, |
| 508 'frogsh' : 100, 'swarm' : 100, 'total' : 100} | 550 'frogsh' : 100, 'swarm' : 100, 'total' : 100} |
| 509 | 551 |
| 510 def RunTests(self): | 552 def RunTests(self): |
| 511 os.chdir('frog') | 553 os.chdir('frog') |
| 512 current_file_path = os.path.join('..', 'tools', 'testing', 'perf_testing', | 554 self.trace_file = os.path.join('..', 'tools', 'testing', 'perf_testing', |
| 513 self.result_folder_name, self.result_folder_name + self.cur_time) | 555 self.result_folder_name, self.result_folder_name + self.cur_time) |
| 514 | 556 |
| 515 self.AddSvnRevisionToTrace(current_file_path) | 557 self.AddSvnRevisionToTrace(self.trace_file) |
| 516 | 558 |
| 517 elapsed = TimeCmd(os.path.join('.', 'frog.py') + | 559 elapsed = TimeCmd([os.path.join('.', 'frog.py'), |
| 518 ' --vm_flags="--compile_all --enable_type_checks --enable_asserts" --' | 560 '--vm_flags="--compile_all --enable_type_checks --enable_asserts"', |
| 519 ' --compile_all --enable_type_checks --out=frogsh frog.dart') | 561 '--', '--compile_all', '--enable_type_checks', '--out=frogsh', |
| 520 RunCmd('echo "%f Compiling on Dart VM in checked mode in' % elapsed + | 562 'frog.dart']) |
| 521 ' seconds" >> %s' % current_file_path) | 563 RunCmd(['echo', '%f Compiling on Dart VM in checked mode in seconds' |
| 522 RunCmd('chmod +x frogsh') | 564 % elapsed], self.trace_file, append=True) |
| 523 elapsed = TimeCmd(os.path.join('.', 'frogsh') + ' --out=frogsh ' | 565 elapsed = TimeCmd([os.path.join('.', 'frogsh'), '--out=frogsh', |
| 524 '--enable_type_checks frog.dart --enable_type_checks ' + | 566 '--enable_type_checks', 'frog.dart', '--enable_type_checks', |
| 525 os.path.join('tests', 'hello.dart')) | 567 os.path.join('tests', 'hello.dart')]) |
| 526 if elapsed < self.failure_threshold['Bootstrapping']: | 568 if elapsed < self.failure_threshold['Bootstrapping']: |
| 527 #frogsh didn't compile correctly. Stop testing now, because subsequent | 569 #frogsh didn't compile correctly. Stop testing now, because subsequent |
| 528 #numbers will be meaningless. | 570 #numbers will be meaningless. |
| 529 return | 571 return |
| 530 size = os.path.getsize('frogsh') | 572 size = os.path.getsize('frogsh') |
| 531 RunCmd('echo "%f Bootstrapping time in seconds in checked mode"' % | 573 RunCmd(['echo', '%f Bootstrapping time in seconds in checked mode' % |
| 532 elapsed + ' >> %s' % current_file_path) | 574 elapsed], self.trace_file, append=True) |
| 533 RunCmd('echo "%d Generated checked frogsh size "' % size + | 575 RunCmd(['echo', '%d Generated checked frogsh size' % size], |
| 534 ' >> %s' % current_file_path) | 576 self.trace_file, append=True) |
| 535 | 577 |
| 536 RunCmd(os.path.join('.', 'frogsh') + ' --out=swarm-result ' | 578 RunCmd([os.path.join('.', 'frogsh'), ' --out=swarm-result ', |
| 537 '--compile-only ' + os.path.join('..', 'client', 'samples', 'swarm', | 579 '--compile-only', os.path.join('..', 'client', 'samples', 'swarm', |
| 538 'swarm.dart')) | 580 'swarm.dart')]) |
| 539 swarm_size = 0 | 581 swarm_size = 0 |
| 540 try: | 582 try: |
| 541 swarm_size = os.path.getsize('swarm-result') | 583 swarm_size = os.path.getsize('swarm-result') |
| 542 except OSError: | 584 except OSError: |
| 543 pass #If compilation failed, continue on running other tests. | 585 pass #If compilation failed, continue on running other tests. |
| 544 | 586 |
| 545 RunCmd(os.path.join('.', 'frogsh') + ' --out=total-result ' | 587 RunCmd([os.path.join('.', 'frogsh'), '--out=total-result', |
| 546 '--compile-only ' + os.path.join('..', 'client', 'samples', 'total', | 588 '--compile-only', os.path.join('..', 'client', 'samples', 'total', |
| 547 'src', 'Total.dart')) | 589 'src', 'Total.dart')]) |
| 548 total_size = 0 | 590 total_size = 0 |
| 549 try: | 591 try: |
| 550 total_size = os.path.getsize('total-result') | 592 total_size = os.path.getsize('total-result') |
| 551 except OSError: | 593 except OSError: |
| 552 pass #If compilation failed, continue on running other tests. | 594 pass #If compilation failed, continue on running other tests. |
| 553 | 595 |
| 554 RunCmd('echo "%d Generated checked swarm size "' % swarm_size + | 596 RunCmd(['echo', '%d Generated checked swarm size' % swarm_size], |
| 555 ' >> %s' % current_file_path) | 597 self.trace_file, append=True) |
| 556 | 598 |
| 557 RunCmd('echo "%d Generated checked total size "' % total_size + | 599 RunCmd(['echo', '%d Generated checked total size' % total_size], |
| 558 ' >> %s' % current_file_path) | 600 self.trace_file, append=True) |
| 559 os.chdir('..') | 601 os.chdir('..') |
| 560 | 602 |
| 561 def ProcessFile(self, afile): | 603 def ProcessFile(self, afile): |
| 562 """Pull all the relevant information out of a given tracefile. | 604 """Pull all the relevant information out of a given tracefile. |
| 563 Args: | 605 Args: |
| 564 afile is the filename string we will be processing.""" | 606 afile is the filename string we will be processing.""" |
| 565 f = open(os.path.join(self.result_folder_name, afile)) | 607 f = open(os.path.join(self.result_folder_name, afile)) |
| 566 tabulate_data = False | 608 tabulate_data = False |
| 567 revision_num = 0 | 609 revision_num = 0 |
| 568 for line in f.readlines(): | 610 for line in f.readlines(): |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 600 'frogsh size', self.values_dict[COMMAND_LINE][FROG]['frogsh'], '', []) | 642 'frogsh size', self.values_dict[COMMAND_LINE][FROG]['frogsh'], '', []) |
| 601 | 643 |
| 602 self.StyleAndSavePerfPlot('Time to compile and bootstrap', | 644 self.StyleAndSavePerfPlot('Time to compile and bootstrap', |
| 603 'Seconds', 10, 10, 'center', '2' + png_filename, [COMMAND_LINE], [FROG], | 645 'Seconds', 10, 10, 'center', '2' + png_filename, [COMMAND_LINE], [FROG], |
| 604 ['Bootstrapping', 'Compiling on Dart VM']) | 646 ['Bootstrapping', 'Compiling on Dart VM']) |
| 605 self.WriteHtml('baz', | 647 self.WriteHtml('baz', |
| 606 self.revision_dict[COMMAND_LINE][FROG]['Bootstrapping'], | 648 self.revision_dict[COMMAND_LINE][FROG]['Bootstrapping'], |
| 607 'Bootstrapping', self.values_dict[COMMAND_LINE][FROG]['Bootstrapping'], | 649 'Bootstrapping', self.values_dict[COMMAND_LINE][FROG]['Bootstrapping'], |
| 608 'Compiling on Dart VM', | 650 'Compiling on Dart VM', |
| 609 self.values_dict[COMMAND_LINE][FROG]['Compiling on Dart VM']) | 651 self.values_dict[COMMAND_LINE][FROG]['Compiling on Dart VM']) |
| 610 | 652 |
| 653 | |
| 654 def ParseArgs(): | |
| 655 parser = optparse.OptionParser() | |
| 656 parser.add_option('--command-line', '-c', dest='cl', | |
| 657 help = 'Run the command line tests', | |
| 658 action = 'store_true', default = False) | |
| 659 parser.add_option('--size-time', '-s', dest = 'size', | |
| 660 help = 'Run the code size and timing tests', | |
| 661 action = 'store_true', default = False) | |
| 662 parser.add_option('--language', '-l', dest = 'language', | |
| 663 help = 'Run the language correctness tests', | |
| 664 action = 'store_true', default = False) | |
| 665 parser.add_option('--browser-perf', '-p', dest = 'perf', | |
| 666 help = 'Run the browser performance tests', | |
| 667 action = 'store_true', default = False) | |
| 668 parser.add_option('--forever', '-f', dest = 'continuous', | |
| 669 help = 'Run this script forever, always checking for the next svn ' | |
| 670 'checkin', action = 'store_true', default = False) | |
| 671 parser.add_option('--perfbot', '-p', dest = 'perfbot', | |
| 672 help = "Run in perfbot mode. (Generate plots, and remove trace files)", | |
| 673 action = 'store_true', default = False) | |
| 674 | |
| 675 args, ignored = parser.parse_args() | |
| 676 if not (args.cl or args.size or args.language or args.perf): | |
| 677 args.cl = args.size = args.language = args.perf = True | |
| 678 return (args.cl, args.size, args.language, args.perf, args.continuous, | |
| 679 args.perfbot) | |
| 680 | |
| 681 def RunTestSequence(cl, size, language, perf): | |
| 682 if PERFBOT_MODE: | |
| 683 # The buildbot already builds and syncs to a specific revision. Don't fight | |
| 684 # with it or replicate work. | |
| 685 SyncAndBuild() | |
| 686 if cl: | |
| 687 CommandLinePerformanceTestRunner('cl-results').Run() | |
| 688 if size: | |
| 689 CompileTimeAndSizeTestRunner('code-time-size').Run() | |
| 690 if language: | |
| 691 BrowserCorrectnessTestRunner('language', 'browser-correctness').Run() | |
| 692 if perf: | |
| 693 BrowserPerformanceTestRunner('browser-perf').Run() | |
| 611 | 694 |
| 612 def main(): | 695 def main(): |
| 613 if HasNewCode(): | 696 (cl, size, language, perf, continuous, perfbot) = ParseArgs() |
| 614 SyncAndBuild() | 697 PERFBOT_MODE = perfbot |
| 615 CommandLinePerformanceTestRunner('cl-results').Run() | 698 if continuous: |
| 616 CompileTimeAndSizeTestRunner('code-time-size').Run() | 699 while True: |
| 617 BrowserCorrectnessTestRunner('language', 'browser-correctness').Run() | 700 if HasNewCode(): |
| 618 BrowserPerformanceTestRunner('browser-perf').Run() | 701 RunTestSequence(cl, size, language, perf) |
| 702 else: | |
| 703 time.sleep(SLEEP_TIME) | |
| 704 else: | |
| 705 RunTestSequence(cl, size, language, perf) | |
| 619 | 706 |
| 620 if __name__ == '__main__': | 707 if __name__ == '__main__': |
| 621 main() | 708 main() |
| 622 | 709 |
| OLD | NEW |