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

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

Issue 9958051: Add support for Dromaeo tests in perf scripts. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments 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 | « tools/testing/perf_testing/index.html ('k') | tools/testing/run_selenium.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/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 getpass 8 import getpass
9 import math 9 import math
10 from matplotlib.font_manager import FontProperties 10 from matplotlib.font_manager import FontProperties
11 import matplotlib.pyplot as plt 11 import matplotlib.pyplot as plt
12 import optparse 12 import optparse
13 import os 13 import os
14 from os.path import dirname, abspath 14 from os.path import dirname, abspath
15 import platform 15 import platform
16 import re
16 import shutil 17 import shutil
17 import stat 18 import stat
18 import subprocess 19 import subprocess
19 import sys 20 import sys
20 import time 21 import time
21 import traceback 22 import traceback
22 23
23 TOOLS_PATH = os.path.join(dirname(dirname(dirname(abspath(__file__))))) 24 TOOLS_PATH = os.path.join(dirname(dirname(dirname(abspath(__file__)))))
24 sys.path.append(TOOLS_PATH) 25 sys.path.append(TOOLS_PATH)
25 import utils 26 import utils
26 27
27 """This script runs to track performance and size progress of 28 """This script runs to track performance and size progress of
28 different svn revisions. It tests to see if there a newer version of the code on 29 different svn revisions. It tests to see if there a newer version of the code on
29 the server, and will sync and run the performance tests if so.""" 30 the server, and will sync and run the performance tests if so."""
30 31
31 DART_INSTALL_LOCATION = os.path.join(dirname(abspath(__file__)), 32 DART_INSTALL_LOCATION = abspath(os.path.join(dirname(abspath(__file__)),
32 '..', '..', '..') 33 '..', '..', '..'))
33 JS_MEAN = 'JS Mean' 34 _suffix = ''
34 FROG_MEAN = 'frog js Mean' 35 if platform.system() == 'Windows':
36 _suffix = '.exe'
37 DART_VM = os.path.join(DART_INSTALL_LOCATION,
38 utils.GetBuildRoot(utils.GuessOS(), 'release', 'ia32'),
39 'dart-sdk',
40 'bin',
41 'dart' + _suffix)
42 DART_COMPILER = os.path.join(DART_INSTALL_LOCATION,
43 utils.GetBuildRoot(utils.GuessOS(),
44 'release', 'ia32'),
45 'dart-sdk',
46 'bin',
47 'frogc')
48
49 GEO_MEAN = 'Geo-Mean'
35 COMMAND_LINE = 'commandline' 50 COMMAND_LINE = 'commandline'
36 JS = 'js' 51 JS = 'js'
37 FROG = 'frog' 52 FROG = 'frog'
38 JS_AND_FROG = [JS, FROG] 53 JS_AND_FROG = [JS, FROG]
39 COLORS = ['blue', 'green', 'red', 'cyan', 'magenta', 'black'] 54 COLORS = ['blue', 'green', 'red', 'cyan', 'magenta', 'black']
40 GRAPH_OUT_DIR = 'graphs' 55 GRAPH_OUT_DIR = 'graphs'
41 56
42 BROWSER_PERF = 'browser-perf' 57 BROWSER_PERF = 'browser-perf'
43 TIME_SIZE = 'code-time-size' 58 TIME_SIZE = 'code-time-size'
44 CL_PERF = 'cl-results' 59 CL_PERF = 'cl-results'
60 DROMAEO = 'dromaeo'
45 61
46 SLEEP_TIME = 200 62 SLEEP_TIME = 200
47 VERBOSE = False 63 VERBOSE = False
48 HAS_SHELL = False 64 HAS_SHELL = False
49 if platform.system() == 'Windows': 65 if platform.system() == 'Windows':
50 # On Windows, shell must be true to get the correct environment variables. 66 # On Windows, shell must be true to get the correct environment variables.
51 HAS_SHELL = True 67 HAS_SHELL = True
52 68
53 """First, some utility methods.""" 69 """First, some utility methods."""
54 70
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 156
141 def has_new_code(): 157 def has_new_code():
142 """Tests if there are any newer versions of files on the server.""" 158 """Tests if there are any newer versions of files on the server."""
143 os.chdir(DART_INSTALL_LOCATION) 159 os.chdir(DART_INSTALL_LOCATION)
144 results = run_cmd(['svn', 'st', '-u']) 160 results = run_cmd(['svn', 'st', '-u'])
145 for line in results: 161 for line in results:
146 if '*' in line: 162 if '*' in line:
147 return True 163 return True
148 return False 164 return False
149 165
166 # TODO(vsm): Add Dartium.
150 def get_browsers(): 167 def get_browsers():
151 browsers = ['ff', 'chrome'] 168 browsers = ['ff', 'chrome']
152 if platform.system() == 'Darwin': 169 if platform.system() == 'Darwin':
153 browsers += ['safari'] 170 browsers += ['safari']
154 if platform.system() == 'Windows': 171 if platform.system() == 'Windows':
155 browsers += ['ie'] 172 browsers += ['ie']
156 return browsers 173 return browsers
157 174
158 def get_versions(): 175 # TODO(vsm): Factor benchmark specific code to a better location.
159 return JS_AND_FROG 176 def get_standalone_benchmarks():
160
161 def get_benchmarks():
162 return ['Mandelbrot', 'DeltaBlue', 'Richards', 'NBody', 'BinaryTrees', 177 return ['Mandelbrot', 'DeltaBlue', 'Richards', 'NBody', 'BinaryTrees',
163 'Fannkuch', 'Meteor', 'BubbleSort', 'Fibonacci', 'Loop', 'Permute', 178 'Fannkuch', 'Meteor', 'BubbleSort', 'Fibonacci', 'Loop', 'Permute',
164 'Queens', 'QuickSort', 'Recurse', 'Sieve', 'Sum', 'Tak', 'Takl', 'Towers', 179 'Queens', 'QuickSort', 'Recurse', 'Sieve', 'Sum', 'Tak', 'Takl', 'Towers',
165 'TreeSort'] 180 'TreeSort']
166 181
167 def get_os_directory(): 182 def get_os_directory():
168 """Specifies the name of the directory for the testing build of dart, which 183 """Specifies the name of the directory for the testing build of dart, which
169 has yet a different naming convention from utils.getBuildRoot(...).""" 184 has yet a different naming convention from utils.getBuildRoot(...)."""
170 if platform.system() == 'Windows': 185 if platform.system() == 'Windows':
171 return 'windows' 186 return 'windows'
172 elif platform.system() == 'Darwin': 187 elif platform.system() == 'Darwin':
173 return 'macos' 188 return 'macos'
174 else: 189 else:
175 return 'linux' 190 return 'linux'
176 191
177 def upload_to_app_engine(username, password): 192 def upload_to_app_engine(username, password):
178 """Upload our results to our appengine server. 193 """Upload our results to our appengine server.
179 Arguments: 194 Arguments:
180 username: App Engine username for uploading data to dartperf.googleplex.com 195 username: App Engine username for uploading data to dartperf.googleplex.com
181 password: App Engine password 196 password: App Engine password
182 """ 197 """
183 # TODO(efortuna): This is the most basic way to get the data up 198 # TODO(efortuna): This is the most basic way to get the data up
184 # for others to view. Revisit this once we're serving nicer graphs (Google 199 # for others to view. Revisit this once we're serving nicer graphs (Google
185 # Chart Tools) and from multiple perfbots and once we're in a position to 200 # Chart Tools) and from multiple perfbots and once we're in a position to
186 # organize the data in a useful manner(!!). 201 # organize the data in a useful manner(!!).
187 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing', 202 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing',
188 'perf_testing')) 203 'perf_testing'))
189 for data in [BROWSER_PERF, TIME_SIZE, CL_PERF]: 204 # TODO(vsm): Factor out this list.
205 for data in [BROWSER_PERF, TIME_SIZE, CL_PERF, DROMAEO]:
190 path = os.path.join('appengine', 'static', 'data', data, utils.GuessOS()) 206 path = os.path.join('appengine', 'static', 'data', data, utils.GuessOS())
191 shutil.rmtree(path, ignore_errors=True) 207 shutil.rmtree(path, ignore_errors=True)
192 os.makedirs(path) 208 os.makedirs(path)
193 files = [] 209 files = []
194 # Copy the 1000 most recent trace files to be uploaded. 210 # Copy the 1000 most recent trace files to be uploaded.
195 for f in os.listdir(data): 211 for f in os.listdir(data):
196 files += [(os.path.getmtime(os.path.join(data, f)), f)] 212 files += [(os.path.getmtime(os.path.join(data, f)), f)]
197 files.sort() 213 files.sort()
198 for f in files[-1000:]: 214 for f in files[-1000:]:
199 shutil.copyfile(os.path.join(data, f[1]), 215 shutil.copyfile(os.path.join(data, f[1]),
200 os.path.join(path, f[1]+'.txt')) 216 os.path.join(path, f[1]+'.txt'))
201 # Generate directory listing. 217 # Generate directory listing.
202 for data in [BROWSER_PERF, TIME_SIZE, CL_PERF]: 218 # TODO(vsm): Factor out this list.
219 for data in [BROWSER_PERF, TIME_SIZE, CL_PERF, DROMAEO]:
203 path = os.path.join('appengine', 'static', 'data', data, utils.GuessOS()) 220 path = os.path.join('appengine', 'static', 'data', data, utils.GuessOS())
204 out = open(os.path.join('appengine', 'static', 221 out = open(os.path.join('appengine', 'static',
205 '%s-%s.html' % (data, utils.GuessOS())), 'w') 222 '%s-%s.html' % (data, utils.GuessOS())), 'w')
206 out.write('<html>\n <body>\n <ul>\n') 223 out.write('<html>\n <body>\n <ul>\n')
207 for f in os.listdir(path): 224 for f in os.listdir(path):
208 if not f.startswith('.'): 225 if not f.startswith('.'):
209 out.write(' <li><a href=data' + \ 226 out.write(' <li><a href=data' + \
210 '''/%(data)s/%(os)s/%(file)s>%(file)s</a></li>\n''' % \ 227 '''/%(data)s/%(os)s/%(file)s>%(file)s</a></li>\n''' % \
211 {'data': data, 'os': utils.GuessOS(), 'file': f}) 228 {'data': data, 'os': utils.GuessOS(), 'file': f})
212 out.write(' </ul>\n </body>\n</html>') 229 out.write(' </ul>\n </body>\n</html>')
(...skipping 11 matching lines...) Expand all
224 'appengine/'], shell=HAS_SHELL, stdin=subprocess.PIPE) 241 'appengine/'], shell=HAS_SHELL, stdin=subprocess.PIPE)
225 p.stdin.write(username + '\n') 242 p.stdin.write(username + '\n')
226 p.stdin.write(password + '\n') 243 p.stdin.write(password + '\n')
227 p.communicate() 244 p.communicate()
228 245
229 246
230 class TestRunner(object): 247 class TestRunner(object):
231 """The base class to provide shared code for different tests we will run and 248 """The base class to provide shared code for different tests we will run and
232 graph.""" 249 graph."""
233 250
234 def __init__(self, result_folder_name, platform_list, js_and_or_frog_list, 251 def __init__(self, result_folder_name, platform_list, variants,
235 values_list): 252 values_list):
236 """Args: 253 """Args:
237 result_folder_name the name of the folder where a tracefile of 254 result_folder_name the name of the folder where a tracefile of
238 performance results will be stored. 255 performance results will be stored.
239 platform_list a list containing the platform(s) that our data has been 256 platform_list a list containing the platform(s) that our data has been
240 run on. (command line, firefox, chrome, etc) 257 run on. (command line, firefox, chrome, etc)
241 js_and_or_frog_list a list specifying whether we hold data about Frog 258 variants a list specifying whether we hold data about Frog
242 generated code, plain JS code (js), or a combination of both. 259 generated code, plain JS code (js), or a combination of both.
243 values_list a list containing the type of data we will be graphing 260 values_list a list containing the type of data we will be graphing
244 (benchmarks, percentage passing, etc)""" 261 (benchmarks, percentage passing, etc)"""
245 self.result_folder_name = result_folder_name 262 self.result_folder_name = result_folder_name
246 # cur_time is used as a timestamp of when this performance test was run. 263 # cur_time is used as a timestamp of when this performance test was run.
247 self.cur_time = str(time.mktime(datetime.datetime.now().timetuple())) 264 self.cur_time = str(time.mktime(datetime.datetime.now().timetuple()))
265 # TODO(vsm): Factor out.
248 self.browser_color = {'chrome': 'green', 'ie': 'blue', 'ff': 'red', 266 self.browser_color = {'chrome': 'green', 'ie': 'blue', 'ff': 'red',
249 'safari':'black'} 267 'safari':'black'}
250 self.values_list = values_list 268 self.values_list = values_list
251 self.platform_list = platform_list 269 self.platform_list = platform_list
252 self.revision_dict = dict() 270 self.revision_dict = dict()
253 self.values_dict = dict() 271 self.values_dict = dict()
254 self.color_index = 0 272 self.color_index = 0
255 for platform in platform_list: 273 for platform in platform_list:
256 self.revision_dict[platform] = dict() 274 self.revision_dict[platform] = dict()
257 self.values_dict[platform] = dict() 275 self.values_dict[platform] = dict()
258 for f in js_and_or_frog_list: 276 for f in variants:
259 self.revision_dict[platform][f] = dict() 277 self.revision_dict[platform][f] = dict()
260 self.values_dict[platform][f] = dict() 278 self.values_dict[platform][f] = dict()
261 for val in values_list: 279 for val in values_list:
262 self.revision_dict[platform][f][val] = [] 280 self.revision_dict[platform][f][val] = []
263 self.values_dict[platform][f][val] = [] 281 self.values_dict[platform][f][val] = []
264 if JS in js_and_or_frog_list: 282 self.revision_dict[platform][f][GEO_MEAN] = []
265 self.revision_dict[platform][JS][JS_MEAN] = [] 283 self.values_dict[platform][f][GEO_MEAN] = []
266 self.values_dict[platform][JS][JS_MEAN] = []
267 if FROG in js_and_or_frog_list:
268 self.revision_dict[platform][FROG][FROG_MEAN] = []
269 self.values_dict[platform][FROG][FROG_MEAN] = []
270 284
271 def get_color(self): 285 def get_color(self):
272 color = COLORS[self.color_index] 286 color = COLORS[self.color_index]
273 self.color_index = (self.color_index + 1) % len(COLORS) 287 self.color_index = (self.color_index + 1) % len(COLORS)
274 return color 288 return color
275 289
276 def style_and_save_perf_plot(self, chart_title, y_axis_label, size_x, size_y, 290 def style_and_save_perf_plot(self, chart_title, y_axis_label, size_x, size_y,
277 legend_loc, filename, platform_list, js_and_or_frog_list, values_list, 291 legend_loc, filename, platform_list, variants, values_list,
278 should_clear_axes=True): 292 should_clear_axes=True):
279 """Sets style preferences for chart boilerplate that is consistent across 293 """Sets style preferences for chart boilerplate that is consistent across
280 all charts, and saves the chart as a png. 294 all charts, and saves the chart as a png.
281 295
282 Args: 296 Args:
283 size_x: the size of the printed chart, in inches, in the horizontal 297 size_x: the size of the printed chart, in inches, in the horizontal
284 direction 298 direction
285 size_y: the size of the printed chart, in inches in the vertical direction 299 size_y: the size of the printed chart, in inches in the vertical direction
286 legend_loc: the location of the legend in on the chart. See suitable 300 legend_loc: the location of the legend in on the chart. See suitable
287 arguments for the loc argument in matplotlib 301 arguments for the loc argument in matplotlib
288 filename: the filename that we want to save the resulting chart as 302 filename: the filename that we want to save the resulting chart as
289 platform_list: a list containing the platform(s) that our data has been 303 platform_list: a list containing the platform(s) that our data has been
290 run on. (command line, firefox, chrome, etc) 304 run on. (command line, firefox, chrome, etc)
291 values_list: a list containing the type of data we will be graphing 305 values_list: a list containing the type of data we will be graphing
292 (performance, percentage passing, etc) 306 (performance, percentage passing, etc)
293 should_clear_axes: True if we want to create a fresh graph, instead of 307 should_clear_axes: True if we want to create a fresh graph, instead of
294 plotting additional lines on the current graph.""" 308 plotting additional lines on the current graph."""
295 if should_clear_axes: 309 if should_clear_axes:
296 plt.cla() # cla = clear current axes 310 plt.cla() # cla = clear current axes
297 for platform in platform_list: 311 for platform in platform_list:
298 for f in js_and_or_frog_list: 312 for f in variants:
299 for val in values_list: 313 for val in values_list:
300 plt.plot(self.revision_dict[platform][f][val], 314 plt.plot(self.revision_dict[platform][f][val],
301 self.values_dict[platform][f][val], 315 self.values_dict[platform][f][val],
302 color=self.get_color(), label='%s-%s-%s' % (platform, f, val)) 316 color=self.get_color(), label='%s-%s-%s' % (platform, f, val))
303 317
304 plt.xlabel('Revision Number') 318 plt.xlabel('Revision Number')
305 plt.ylabel(y_axis_label) 319 plt.ylabel(y_axis_label)
306 plt.title(chart_title) 320 plt.title(chart_title)
307 fontP = FontProperties() 321 fontP = FontProperties()
308 fontP.set_size('small') 322 fontP.set_size('small')
(...skipping 12 matching lines...) Expand all
321 for line in output.split('\n'): 335 for line in output.split('\n'):
322 if 'Revision' in line: 336 if 'Revision' in line:
323 run_cmd(['echo', line.strip()], outfile) 337 run_cmd(['echo', line.strip()], outfile)
324 return True 338 return True
325 return False 339 return False
326 340
327 if not search_for_revision(['svn', 'info']): 341 if not search_for_revision(['svn', 'info']):
328 if not search_for_revision(['git', 'svn', 'info']): 342 if not search_for_revision(['git', 'svn', 'info']):
329 run_cmd(['echo', 'Revision: unknown'], outfile) 343 run_cmd(['echo', 'Revision: unknown'], outfile)
330 344
331 def calculate_geometric_mean(self, platform, frog_or_js, svn_revision): 345 def calculate_geometric_mean(self, platform, variant, svn_revision):
332 """Calculate the aggregate geometric mean for JS and frog benchmark sets, 346 """Calculate the aggregate geometric mean for JS and frog benchmark sets,
333 given two benchmark dictionaries.""" 347 given two benchmark dictionaries."""
334 geo_mean = 0 348 geo_mean = 0
335 for benchmark in get_benchmarks(): 349 for benchmark in self.values_list:
336 geo_mean += math.log(self.values_dict[platform][frog_or_js][benchmark][ 350 geo_mean += math.log(self.values_dict[platform][variant][benchmark][
337 len(self.values_dict[platform][frog_or_js][benchmark]) - 1]) 351 len(self.values_dict[platform][variant][benchmark]) - 1])
338 352
339 mean = JS_MEAN 353 self.values_dict[platform][variant][GEO_MEAN] += \
340 if frog_or_js == FROG: 354 [math.pow(math.e, geo_mean / len(self.values_list))]
341 mean = FROG_MEAN 355 self.revision_dict[platform][variant][GEO_MEAN] += [svn_revision]
342 self.values_dict[platform][frog_or_js][mean] += \
343 [math.pow(math.e, geo_mean / len(get_benchmarks()))]
344 self.revision_dict[platform][frog_or_js][mean] += [svn_revision]
345 356
346 def run(self, graph_only): 357 def run(self, graph_only):
347 """Run the benchmarks/tests from the command line and plot the 358 """Run the benchmarks/tests from the command line and plot the
348 results.""" 359 results."""
349 plt.cla() # cla = clear current axes 360 plt.cla() # cla = clear current axes
350 os.chdir(DART_INSTALL_LOCATION) 361 os.chdir(DART_INSTALL_LOCATION)
351 ensure_output_directory(self.result_folder_name) 362 ensure_output_directory(self.result_folder_name)
352 ensure_output_directory(GRAPH_OUT_DIR) 363 ensure_output_directory(GRAPH_OUT_DIR)
353 if not graph_only: 364 if not graph_only:
354 self.run_tests() 365 self.run_tests()
355 366
356 os.chdir(os.path.join('tools', 'testing', 'perf_testing')) 367 os.chdir(os.path.join('tools', 'testing', 'perf_testing'))
357 368
358 # TODO(efortuna): You will want to make this only use a subset of the files 369 # TODO(efortuna): You will want to make this only use a subset of the files
359 # eventually. 370 # eventually.
360 files = os.listdir(self.result_folder_name) 371 files = os.listdir(self.result_folder_name)
361 372
362 for afile in files: 373 for afile in files:
363 if not afile.startswith('.'): 374 if not afile.startswith('.'):
364 self.process_file(afile) 375 self.process_file(afile)
365 376
366 self.plot_results('%s.png' % self.result_folder_name) 377 self.plot_results('%s.png' % self.result_folder_name)
367 378
368 class PerformanceTest(TestRunner): 379 class PerformanceTest(TestRunner):
369 """Super class for all performance testing.""" 380 """Super class for all performance testing."""
370 def __init__(self, result_folder_name, platform_list, platform_type): 381 def __init__(self, result_folder_name, platform_list, platform_type,
382 versions, benchmarks):
371 super(PerformanceTest, self).__init__(result_folder_name, 383 super(PerformanceTest, self).__init__(result_folder_name,
372 platform_list, get_versions(), get_benchmarks()) 384 platform_list, versions, benchmarks)
373 self.platform_list = platform_list 385 self.platform_list = platform_list
374 self.platform_type = platform_type 386 self.platform_type = platform_type
387 self.versions = versions
388 self.benchmarks = benchmarks
375 389
376 def plot_all_perf(self, png_filename): 390 def plot_all_perf(self, png_filename):
377 """Create a plot that shows the performance changes of individual benchmarks 391 """Create a plot that shows the performance changes of individual benchmarks
378 run by JS and generated by frog, over svn history.""" 392 run by JS and generated by frog, over svn history."""
379 for benchmark in get_benchmarks(): 393 for benchmark in self.benchmarks:
380 self.style_and_save_perf_plot( 394 self.style_and_save_perf_plot(
381 'Performance of %s over time on the %s on %s' % (benchmark, 395 'Performance of %s over time on the %s on %s' % (benchmark,
382 self.platform_type, utils.GuessOS()), 'Speed (bigger = better)', 16, 396 self.platform_type, utils.GuessOS()), 'Speed (bigger = better)', 16,
383 14, 'lower left', benchmark + png_filename, self.platform_list, 397 14, 'lower left', benchmark + png_filename, self.platform_list,
384 get_versions(), [benchmark]) 398 self.versions, [benchmark])
385 399
386 def plot_avg_perf(self, png_filename): 400 def plot_avg_perf(self, png_filename):
387 """Generate a plot that shows the performance changes of the geomentric mean 401 """Generate a plot that shows the performance changes of the geomentric mean
388 of JS and frog benchmark performance over svn history.""" 402 of JS and frog benchmark performance over svn history."""
389 (title, y_axis, size_x, size_y, loc, filename) = \ 403 (title, y_axis, size_x, size_y, loc, filename) = \
390 ('Geometric Mean of benchmark %s performance on %s ' % 404 ('Geometric Mean of benchmark %s performance on %s ' %
391 (self.platform_type, utils.GuessOS()), 'Speed (bigger = better)', 16, 5, 405 (self.platform_type, utils.GuessOS()), 'Speed (bigger = better)', 16, 5,
392 'lower left', 'avg'+png_filename) 406 'lower left', 'avg'+png_filename)
393 clear_axis = True 407 clear_axis = True
394 for platform in self.platform_list: 408 for platform in self.platform_list:
395 self.style_and_save_perf_plot(title, y_axis, size_x, size_y, loc, 409 for version in self.versions:
396 filename, [platform], [JS], [JS_MEAN], clear_axis) 410 self.style_and_save_perf_plot(title, y_axis, size_x, size_y, loc,
397 clear_axis = False 411 filename, [platform], [version],
398 self.style_and_save_perf_plot(title, y_axis, size_x, size_y, loc, 412 [GEO_MEAN], clear_axis)
399 filename, [platform], [FROG], [FROG_MEAN], clear_axis) 413 clear_axis = False
400 414
401 def plot_results(self, png_filename): 415 def plot_results(self, png_filename):
402 self.plot_all_perf(png_filename) 416 self.plot_all_perf(png_filename)
403 self.plot_avg_perf('2' + png_filename) 417 self.plot_avg_perf('2' + png_filename)
404 418
405 419
406 class CommandLinePerformanceTest(PerformanceTest): 420 class CommandLinePerformanceTest(PerformanceTest):
407 """Run performance tests from the command line.""" 421 """Run performance tests from the command line."""
408 422
409 def __init__(self, result_folder_name): 423 def __init__(self):
410 super(CommandLinePerformanceTest, self).__init__(result_folder_name, 424 super(CommandLinePerformanceTest, self).__init__(
411 [COMMAND_LINE], 'command line') 425 CL_PERF, [COMMAND_LINE], 'command line',
426 JS_AND_FROG, get_standalone_benchmarks())
412 427
413 def process_file(self, afile): 428 def process_file(self, afile):
414 """Pull all the relevant information out of a given tracefile. 429 """Pull all the relevant information out of a given tracefile.
415 430
416 Args: 431 Args:
417 afile: The filename string we will be processing.""" 432 afile: The filename string we will be processing."""
418 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing', 433 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing',
419 'perf_testing')) 434 'perf_testing'))
420 f = open(os.path.join(self.result_folder_name, afile)) 435 f = open(os.path.join(self.result_folder_name, afile))
421 tabulate_data = False 436 tabulate_data = False
422 revision_num = 0 437 revision_num = 0
423 for line in f.readlines(): 438 for line in f.readlines():
424 if 'Revision' in line: 439 if 'Revision' in line:
425 revision_num = int(line.split()[1]) 440 revision_num = int(line.split()[1])
426 elif 'Benchmark' in line: 441 elif 'Benchmark' in line:
427 tabulate_data = True 442 tabulate_data = True
428 elif tabulate_data: 443 elif tabulate_data:
429 tokens = line.split() 444 tokens = line.split()
430 if len(tokens) < 4 or tokens[0] not in get_benchmarks(): 445 if len(tokens) < 4 or tokens[0] not in self.benchmarks:
431 #Done tabulating data. 446 #Done tabulating data.
432 break 447 break
433 js_value = float(tokens[1]) 448 js_value = float(tokens[1])
434 frog_value = float(tokens[3]) 449 frog_value = float(tokens[3])
435 if js_value == 0 or frog_value == 0: 450 if js_value == 0 or frog_value == 0:
436 #Then there was an error when this performance test was run. Do not 451 #Then there was an error when this performance test was run. Do not
437 #count it in our numbers. 452 #count it in our numbers.
438 return 453 return
439 benchmark = tokens[0] 454 benchmark = tokens[0]
440 self.revision_dict[COMMAND_LINE][JS][benchmark] += [revision_num] 455 self.revision_dict[COMMAND_LINE][JS][benchmark] += [revision_num]
441 self.values_dict[COMMAND_LINE][JS][benchmark] += [js_value] 456 self.values_dict[COMMAND_LINE][JS][benchmark] += [js_value]
442 self.revision_dict[COMMAND_LINE][FROG][benchmark] += [revision_num] 457 self.revision_dict[COMMAND_LINE][FROG][benchmark] += [revision_num]
443 self.values_dict[COMMAND_LINE][FROG][benchmark] += [frog_value] 458 self.values_dict[COMMAND_LINE][FROG][benchmark] += [frog_value]
444 f.close() 459 f.close()
445 460
446 self.calculate_geometric_mean(COMMAND_LINE, FROG, revision_num) 461 self.calculate_geometric_mean(COMMAND_LINE, FROG, revision_num)
447 self.calculate_geometric_mean(COMMAND_LINE, JS, revision_num) 462 self.calculate_geometric_mean(COMMAND_LINE, JS, revision_num)
448 463
449 def run_tests(self): 464 def run_tests(self):
450 """Run a performance test on our updated system.""" 465 """Run a performance test on our updated system."""
451 os.chdir('frog') 466 os.chdir('frog')
452 self.trace_file = os.path.join('..', 'tools', 'testing', 'perf_testing', 467 self.trace_file = os.path.join('..', 'tools', 'testing', 'perf_testing',
453 self.result_folder_name, 'result' + self.cur_time) 468 self.result_folder_name, 'result' + self.cur_time)
454 run_cmd(['python', os.path.join('benchmarks', 'perf_tests.py')], 469 run_cmd(['python', os.path.join('benchmarks', 'perf_tests.py')],
455 self.trace_file) 470 self.trace_file)
456 os.chdir('..') 471 os.chdir('..')
457 472
458 473
459 class BrowserPerformanceTest(PerformanceTest): 474 class BrowserStandalonePerformanceTest(PerformanceTest):
460 """Runs performance tests, in the browser.""" 475 """Runs standalone performance tests, in the browser."""
461 476
462 def __init__(self, result_folder_name): 477 def __init__(self):
463 super(BrowserPerformanceTest, self).__init__( 478 super(BrowserStandalonePerformanceTest, self).__init__(
464 result_folder_name, get_browsers(), 'browser') 479 BROWSER_PERF, get_browsers(), 'browser',
480 JS_AND_FROG, get_standalone_benchmarks())
465 481
466 def run_tests(self): 482 def run_tests(self):
467 """Run a performance test in the browser.""" 483 """Run a performance test in the browser."""
468 484
469 os.chdir('frog') 485 os.chdir('frog')
470 run_cmd(['python', os.path.join('benchmarks', 'make_web_benchmarks.py')]) 486 run_cmd(['python', os.path.join('benchmarks', 'make_web_benchmarks.py')])
471 os.chdir('..') 487 os.chdir('..')
472 488
473 for browser in get_browsers(): 489 for browser in get_browsers():
474 for version in get_versions(): 490 for version in self.versions:
475 self.trace_file = os.path.join('tools', 'testing', 'perf_testing', 491 self.trace_file = os.path.join('tools', 'testing', 'perf_testing',
476 self.result_folder_name, 492 self.result_folder_name,
477 'perf-%s-%s-%s' % (self.cur_time, browser, version)) 493 'perf-%s-%s-%s' % (self.cur_time, browser, version))
478 self.add_svn_revision_to_trace(self.trace_file) 494 self.add_svn_revision_to_trace(self.trace_file)
479 file_path = os.path.join(os.getcwd(), 'internal', 'browserBenchmarks', 495 file_path = os.path.join(os.getcwd(), 'internal', 'browserBenchmarks',
480 'benchmark_page_%s.html' % version) 496 'benchmark_page_%s.html' % version)
481 run_cmd(['python', os.path.join('tools', 'testing', 'run_selenium.py'), 497 run_cmd(['python', os.path.join('tools', 'testing', 'run_selenium.py'),
482 '--out', file_path, '--browser', browser, 498 '--out', file_path, '--browser', browser,
483 '--timeout', '600', '--perf'], self.trace_file, append=True) 499 '--timeout', '600', '--perf'], self.trace_file, append=True)
484 500
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 bench_dict = self.values_dict[browser][JS] 538 bench_dict = self.values_dict[browser][JS]
523 else: 539 else:
524 bench_dict = self.values_dict[browser][FROG] 540 bench_dict = self.values_dict[browser][FROG]
525 bench_dict[name] += [float(score)] 541 bench_dict[name] += [float(score)]
526 self.revision_dict[browser][version][name] += [revision_num] 542 self.revision_dict[browser][version][name] += [revision_num]
527 543
528 f.close() 544 f.close()
529 self.calculate_geometric_mean(browser, version, revision_num) 545 self.calculate_geometric_mean(browser, version, revision_num)
530 546
531 547
548 # TODO(vsm): This should not be hardcoded here if possible.
549 def get_dromaeo_benchmarks():
550 return map(lambda str: str.replace(' ', '_'),
551 ['getAttribute', 'element.property', 'setAttribute',
552 'element.property = value', 'createElement', 'createTextNode',
553 'innerHTML', 'cloneNode', 'appendChild', 'insertBefore',
554 'getElementById', 'getElementById (not in document)',
555 'getElementsByTagName(div)', 'getElementsByTagName(p)',
556 'getElementsByTagName(a)', 'getElementsByTagName(*)',
557 'getElementsByTagName (not in document)', 'getElementsByName',
558 'getElementsByName (not in document)', 'firstChild', 'lastChild',
559 'nextSibling', 'previousSibling', 'childNodes'])
560
561
562 def get_dromaeo_versions():
563 return ['js', 'frog_dom', 'frog_html']
564
565 class DromaeoTest(PerformanceTest):
566 """Runs Dromaeo tests, in the browser."""
567 def __init__(self):
568 super(DromaeoTest, self).__init__(
569 DROMAEO, get_browsers(), 'browser',
570 get_dromaeo_versions(), get_dromaeo_benchmarks())
571
572 def run_tests(self):
573 """Run dromaeo in the browser."""
574
575 # Build tests.
576 dromaeo_path = os.path.join('samples', 'third_party', 'dromaeo')
577 current_path = os.getcwd()
578 os.chdir(dromaeo_path)
579 run_cmd(['python', 'generate_frog_tests.py'])
580 os.chdir(current_path)
581
582 versions = get_dromaeo_versions()
583
584 for browser in get_browsers():
585 for version_name in versions:
586 version = version_name.replace('_','&')
587 self.trace_file = os.path.join('tools', 'testing', 'perf_testing',
588 self.result_folder_name,
589 'dromaeo-%s-%s-%s' % (self.cur_time, browser, version_name))
590 self.add_svn_revision_to_trace(self.trace_file)
591 file_path = os.path.join(os.getcwd(), dromaeo_path,
592 'index-js.html?%s' % version)
593 run_cmd(['python', os.path.join('tools', 'testing', 'run_selenium.py'),
594 '--out', file_path, '--browser', browser,
595 '--timeout', '200', '--dromaeo'], self.trace_file, append=True)
596
597 def process_file(self, afile):
598 """Comb through the html to find the performance results."""
599 parts = afile.split('-')
600 browser = parts[2]
601 version = parts[3]
602
603 bench_dict = self.values_dict[browser][version]
604
605 f = open(os.path.join(self.result_folder_name, afile))
606 lines = f.readlines()
607 i = 0
608 revision_num = 0
609 revision_pattern = r'Revision: (\d+)'
610 suite_pattern = r'<div class="result-item done">(.+?)</ol></div>'
611 result_pattern = r'<b>(.+?)</b>(.+?)<small> runs/s(.+)'
612
613 for line in lines:
614 rev = re.match(revision_pattern, line.strip())
615 if rev:
616 revision_num = int(rev.group(1))
617 continue
618
619 suite_results = re.findall(suite_pattern, line)
620 if suite_results:
621 for suite_result in suite_results:
622 results = re.findall(r'<li>(.*?)</li>', suite_result)
623 if results:
624 for result in results:
625 r = re.match(result_pattern, result)
626 name = r.group(1).strip(':').replace(' ', '_')
627 score = float(r.group(2))
628 bench_dict[name] += [float(score)]
629 self.revision_dict[browser][version][name] += [revision_num]
630
631 f.close()
632 self.calculate_geometric_mean(browser, version, revision_num)
633
634
532 class CompileTimeAndSizeTest(TestRunner): 635 class CompileTimeAndSizeTest(TestRunner):
533 """Run tests to determine how long minfrog takes to compile, and the compiled 636 """Run tests to determine how long minfrog takes to compile, and the compiled
534 file output size of some benchmarking files.""" 637 file output size of some benchmarking files."""
535 def __init__(self, result_folder_name): 638 def __init__(self):
536 super(CompileTimeAndSizeTest, self).__init__(result_folder_name, 639 super(CompileTimeAndSizeTest, self).__init__(TIME_SIZE,
537 [COMMAND_LINE], [FROG], ['Compiling on Dart VM', 'Bootstrapping', 640 [COMMAND_LINE], [FROG], ['Compiling on Dart VM', 'Bootstrapping',
538 'minfrog', 'swarm', 'total']) 641 'minfrog', 'swarm', 'total'])
539 self.failure_threshold = {'Compiling on Dart VM' : 1, 'Bootstrapping' : .5, 642 self.failure_threshold = {'Compiling on Dart VM' : 1, 'Bootstrapping' : .5,
540 'minfrog' : 100, 'swarm' : 100, 'total' : 100} 643 'minfrog' : 100, 'swarm' : 100, 'total' : 100}
541 644
542 def run_tests(self): 645 def run_tests(self):
543 os.chdir('frog') 646 os.chdir('frog')
544 self.trace_file = os.path.join('..', 'tools', 'testing', 'perf_testing', 647 self.trace_file = os.path.join('..', 'tools', 'testing', 'perf_testing',
545 self.result_folder_name, self.result_folder_name + self.cur_time) 648 self.result_folder_name, self.result_folder_name + self.cur_time)
546 649
547 self.add_svn_revision_to_trace(self.trace_file) 650 self.add_svn_revision_to_trace(self.trace_file)
548 651
549 suffix = '' 652 elapsed = time_cmd([DART_VM, os.path.join('.', 'minfrogc.dart'),
550 if platform.system() == 'Windows':
551 suffix = '.exe'
552 elapsed = time_cmd([os.path.join('..', utils.GetBuildRoot(utils.GuessOS(),
553 'release', 'ia32'), 'dart' + suffix), os.path.join('.', 'minfrogc.dart'),
554 '--out=minfrog', 'minfrog.dart']) 653 '--out=minfrog', 'minfrog.dart'])
555 run_cmd(['echo', '%f Compiling on Dart VM in production mode in seconds' 654 run_cmd(['echo', '%f Compiling on Dart VM in production mode in seconds'
556 % elapsed], self.trace_file, append=True) 655 % elapsed], self.trace_file, append=True)
557 elapsed = time_cmd([os.path.join('.', 'minfrog'), '--out=minfrog', 656 elapsed = time_cmd([os.path.join('.', 'minfrog'), '--out=minfrog',
558 'minfrog.dart', os.path.join('tests', 'hello.dart')]) 657 'minfrog.dart', os.path.join('tests', 'hello.dart')])
559 if elapsed < self.failure_threshold['Bootstrapping']: 658 if elapsed < self.failure_threshold['Bootstrapping']:
560 #minfrog didn't compile correctly. Stop testing now, because subsequent 659 #minfrog didn't compile correctly. Stop testing now, because subsequent
561 #numbers will be meaningless. 660 #numbers will be meaningless.
562 return 661 return
563 size = os.path.getsize('minfrog') 662 size = os.path.getsize('minfrog')
564 run_cmd(['echo', '%f Bootstrapping time in seconds in production mode' % 663 run_cmd(['echo', '%f Bootstrapping time in seconds in production mode' %
565 elapsed], self.trace_file, append=True) 664 elapsed], self.trace_file, append=True)
566 run_cmd(['echo', '%d Generated checked minfrog size' % size], 665 run_cmd(['echo', '%d Generated checked minfrog size' % size],
567 self.trace_file, append=True) 666 self.trace_file, append=True)
568 667
569 run_cmd([os.path.join('.', 'minfrog'), '--out=swarm-result', 668 run_cmd([DART_COMPILER, '--out=swarm-result',
570 '--compile-only', os.path.join('..', 'samples', 'swarm', 669 os.path.join('..', 'samples', 'swarm',
571 'swarm.dart')]) 670 'swarm.dart')])
572 swarm_size = 0 671 swarm_size = 0
573 try: 672 try:
574 swarm_size = os.path.getsize('swarm-result') 673 swarm_size = os.path.getsize('swarm-result')
575 except OSError: 674 except OSError:
576 pass #If compilation failed, continue on running other tests. 675 pass #If compilation failed, continue on running other tests.
577 676
578 run_cmd([os.path.join('.', 'minfrog'), '--out=total-result', 677 run_cmd([DART_COMPILER, '--out=total-result',
579 '--compile-only', os.path.join('..', 'samples', 'total', 678 os.path.join('..', 'samples', 'total',
580 'client', 'Total.dart')]) 679 'client', 'Total.dart')])
581 total_size = 0 680 total_size = 0
582 try: 681 try:
583 total_size = os.path.getsize('total-result') 682 total_size = os.path.getsize('total-result')
584 except OSError: 683 except OSError:
585 pass #If compilation failed, continue on running other tests. 684 pass #If compilation failed, continue on running other tests.
586 685
587 run_cmd(['echo', '%d Generated checked swarm size' % swarm_size], 686 run_cmd(['echo', '%d Generated checked swarm size' % swarm_size],
588 self.trace_file, append=True) 687 self.trace_file, append=True)
589 688
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 self.style_and_save_perf_plot('Compiled minfrog Sizes', 731 self.style_and_save_perf_plot('Compiled minfrog Sizes',
633 'Size (in bytes)', 10, 10, 'lower left', png_filename, [COMMAND_LINE], 732 'Size (in bytes)', 10, 10, 'lower left', png_filename, [COMMAND_LINE],
634 [FROG], ['swarm', 'total', 'minfrog']) 733 [FROG], ['swarm', 'total', 'minfrog'])
635 734
636 self.style_and_save_perf_plot('Time to compile and bootstrap', 735 self.style_and_save_perf_plot('Time to compile and bootstrap',
637 'Seconds', 10, 10, 'lower left', '2' + png_filename, [COMMAND_LINE], 736 'Seconds', 10, 10, 'lower left', '2' + png_filename, [COMMAND_LINE],
638 [FROG], ['Bootstrapping', 'Compiling on Dart VM']) 737 [FROG], ['Bootstrapping', 'Compiling on Dart VM'])
639 738
640 def parse_args(): 739 def parse_args():
641 parser = optparse.OptionParser() 740 parser = optparse.OptionParser()
741 # TODO(vsm): Change to a list to scale.
642 parser.add_option('--command-line', '-c', dest='cl', 742 parser.add_option('--command-line', '-c', dest='cl',
643 help='Run the command line tests', 743 help='Run the command line tests',
644 action='store_true', default=False) 744 action='store_true', default=False)
645 parser.add_option('--size-time', '-s', dest='size', 745 parser.add_option('--size-time', '-s', dest='size',
646 help='Run the code size and timing tests', 746 help='Run the code size and timing tests',
647 action='store_true', default=False) 747 action='store_true', default=False)
648 parser.add_option('--browser-perf', '-b', dest='perf', 748 parser.add_option('--browser-perf', '-b', dest='perf',
649 help='Run the browser performance tests', 749 help='Run the browser performance tests',
650 action='store_true', default=False) 750 action='store_true', default=False)
751 parser.add_option('--dromaeo', '-d', dest='dromaeo',
752 help='Run the Dromaeo performance tests',
753 action='store_true', default=False)
651 parser.add_option('--forever', '-f', dest='continuous', 754 parser.add_option('--forever', '-f', dest='continuous',
652 help='Run this script forever, always checking for the next svn ' 755 help='Run this script forever, always checking for the next svn '
653 'checkin', action='store_true', default=False) 756 'checkin', action='store_true', default=False)
654 parser.add_option('--verbose', '-v', dest='verbose', 757 parser.add_option('--verbose', '-v', dest='verbose',
655 help='Print extra debug output', action='store_true', default=False) 758 help='Print extra debug output', action='store_true', default=False)
656 parser.add_option('--nobuild', '-n', dest='no_build', action='store_true', 759 parser.add_option('--nobuild', '-n', dest='no_build', action='store_true',
657 help='Do not sync with the repository and do not rebuild.', default=False) 760 help='Do not sync with the repository and do not rebuild.', default=False)
658 parser.add_option('--graph-only', '-g', dest='graph_only', default=False, 761 parser.add_option('--graph-only', '-g', dest='graph_only', default=False,
659 help='Do not run tests, only regenerate graphs', action='store_true') 762 help='Do not run tests, only regenerate graphs', action='store_true')
660 parser.add_option('--user', '-u', dest='username', 763 parser.add_option('--user', '-u', dest='username',
661 help='Username for submitting new data to App Engine', default='') 764 help='Username for submitting new data to App Engine', default='')
662 765
663 args, ignored = parser.parse_args() 766 args, ignored = parser.parse_args()
664 password = '' 767 password = ''
665 if args.username != '': 768 if args.username != '':
666 password = getpass.getpass("App Engine Password: ") 769 password = getpass.getpass("App Engine Password: ")
667 else: 770 else:
668 print 'Warning: performance data will not be uploaded to App Engine' + \ 771 print 'Warning: performance data will not be uploaded to App Engine' + \
669 ' if you do not provide a username.' 772 ' if you do not provide a username.'
670 if not (args.cl or args.size or args.perf): 773 if not (args.cl or args.size or args.perf or args.dromaeo):
671 args.cl = args.size = args.perf = True 774 args.cl = args.size = args.perf = args.dromaeo = True
672 return (args.cl, args.size, args.perf, args.continuous, 775 return (args.cl, args.size, args.perf, args.dromaeo, args.continuous,
673 args.verbose, args.no_build, args.graph_only, 776 args.verbose, args.no_build, args.graph_only,
674 args.username, password) 777 args.username, password)
675 778
676 def run_test_sequence(cl, size, perf, no_build, graph_only, 779 def run_test_sequence(cl, size, perf, dromaeo, no_build, graph_only,
677 username, password): 780 username, password):
678 # The buildbot already builds and syncs to a specific revision. Don't fight 781 # The buildbot already builds and syncs to a specific revision. Don't fight
679 # with it or replicate work. 782 # with it or replicate work.
680 if (not no_build or not graph_only) and sync_and_build() == 1: 783 if (not no_build or not graph_only) and sync_and_build() == 1:
681 return # The build is broken. 784 return # The build is broken.
682 if size: 785 if size:
683 CompileTimeAndSizeTest(TIME_SIZE).run(graph_only) 786 CompileTimeAndSizeTest().run(graph_only)
684 if cl: 787 if cl:
685 CommandLinePerformanceTest(CL_PERF).run(graph_only) 788 CommandLinePerformanceTest().run(graph_only)
686 if perf: 789 if perf:
687 BrowserPerformanceTest(BROWSER_PERF).run(graph_only) 790 BrowserStandalonePerformanceTest().run(graph_only)
791 if dromaeo:
792 DromaeoTest().run(graph_only)
688 793
689 if username != '': 794 if username != '':
690 upload_to_app_engine(username, password) 795 upload_to_app_engine(username, password)
691 796
692 def main(): 797 def main():
693 global VERBOSE 798 global VERBOSE
694 (cl, size, perf, continuous, verbose, no_build, graph_only, 799 (cl, size, perf, dromaeo, continuous, verbose, no_build, graph_only,
695 username, password) = parse_args() 800 username, password) = parse_args()
696 VERBOSE = verbose 801 VERBOSE = verbose
697 if continuous: 802 if continuous:
698 while True: 803 while True:
699 if has_new_code(): 804 if has_new_code():
700 run_test_sequence(cl, size, perf, no_build, graph_only, 805 run_test_sequence(cl, size, perf, dromaeo, no_build, graph_only,
701 username, password) 806 username, password)
702 else: 807 else:
703 time.sleep(SLEEP_TIME) 808 time.sleep(SLEEP_TIME)
704 else: 809 else:
705 run_test_sequence(cl, size, perf, no_build, graph_only, 810 run_test_sequence(cl, size, perf, dromaeo, no_build, graph_only,
706 username, password) 811 username, password)
707 812
708 if __name__ == '__main__': 813 if __name__ == '__main__':
709 main() 814 main()
OLDNEW
« no previous file with comments | « tools/testing/perf_testing/index.html ('k') | tools/testing/run_selenium.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698