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

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

Issue 9933002: Some clean up on run_perf_test (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Change v8 to js 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 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 shutil 16 import shutil
17 import stat 17 import stat
18 import subprocess 18 import subprocess
19 import sys 19 import sys
20 import time 20 import time
21 import traceback 21 import traceback
22 22
23 TOOLS_PATH = os.path.join(dirname(dirname(dirname(abspath(__file__))))) 23 TOOLS_PATH = os.path.join(dirname(dirname(dirname(abspath(__file__)))))
24 sys.path.append(TOOLS_PATH) 24 sys.path.append(TOOLS_PATH)
25 import utils 25 import utils
26 26
27 """This script runs to track performance and correctness progress of 27 """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 28 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.""" 29 the server, and will sync and run the performance tests if so."""
30 30
31 DART_INSTALL_LOCATION = os.path.join(dirname(abspath(__file__)), 31 DART_INSTALL_LOCATION = os.path.join(dirname(abspath(__file__)),
32 '..', '..', '..') 32 '..', '..', '..')
33 JS_MEAN = 'JS Mean' 33 JS_MEAN = 'JS Mean'
34 FROG_MEAN = 'frog js Mean' 34 FROG_MEAN = 'frog js Mean'
35 COMMAND_LINE = 'commandline' 35 COMMAND_LINE = 'commandline'
36 JS = 'js' 36 JS = 'js'
37 FROG = 'frog' 37 FROG = 'frog'
38 JS_AND_FROG = [JS, FROG] 38 JS_AND_FROG = [JS, FROG]
39 CORRECTNESS = 'Percent passing'
40 COLORS = ['blue', 'green', 'red', 'cyan', 'magenta', 'black'] 39 COLORS = ['blue', 'green', 'red', 'cyan', 'magenta', 'black']
41 GRAPH_OUT_DIR = 'graphs' 40 GRAPH_OUT_DIR = 'graphs'
42 41
43 BROWSER_PERF = 'browser-perf' 42 BROWSER_PERF = 'browser-perf'
44 TIME_SIZE = 'code-time-size' 43 TIME_SIZE = 'code-time-size'
45 CL_PERF = 'cl-results' 44 CL_PERF = 'cl-results'
46 BROWSER_CORRECTNESS = 'browser-correctness'
47 45
48 SLEEP_TIME = 200 46 SLEEP_TIME = 200
49 VERBOSE = False 47 VERBOSE = False
50 HAS_SHELL = False 48 HAS_SHELL = False
51 if platform.system() == 'Windows': 49 if platform.system() == 'Windows':
52 # On Windows, shell must be true to get the correct environment variables. 50 # On Windows, shell must be true to get the correct environment variables.
53 HAS_SHELL = True 51 HAS_SHELL = True
54 52
55 """First, some utility methods.""" 53 """First, some utility methods."""
56 54
57 def run_cmd(cmd_list, outfile=None, append=False): 55 def run_cmd(cmd_list, outfile=None, append=False):
58 """Run the specified command and print out any output to stdout. 56 """Run the specified command and print out any output to stdout.
59 57
60 Args: 58 Args:
61 cmd_list: a list of strings that make up the command to run 59 cmd_list: a list of strings that make up the command to run
62 outfile: a string indicating the name of the file that we should write 60 outfile: a string indicating the name of the file that we should write
63 stdout to 61 stdout to
64 append: True if we want to append to the file instead of overwriting it""" 62 append: True if we want to append to the file instead of overwriting it"""
65 if VERBOSE: 63 if VERBOSE:
66 print ' '.join(cmd_list) 64 print ' '.join(cmd_list)
67 out = subprocess.PIPE 65 out = subprocess.PIPE
68 if outfile: 66 if outfile:
69 mode = 'w' 67 mode = 'w'
70 if append: 68 if append:
71 mode = 'a' 69 mode = 'a'
72 out = open(outfile, mode) 70 out = open(outfile, mode)
73 if append: 71 if append:
74 # Annoying Windows "feature" -- append doesn't actually append unless you 72 # Annoying Windows "feature" -- append doesn't actually append unless you
75 # explicitly go to the end of the file. 73 # explicitly go to the end of the file.
76 # http://mail.python.org/pipermail/python-list/2009-October/1221859.html 74 # http://mail.python.org/pipermail/python-list/2009-October/1221859.html
77 out.seek(0, os.SEEK_END) 75 out.seek(0, os.SEEK_END)
78 p = subprocess.Popen(cmd_list, stdout = out, stderr = subprocess.PIPE, 76 p = subprocess.Popen(cmd_list, stdout = out, stderr = subprocess.PIPE,
79 shell=HAS_SHELL) 77 shell=HAS_SHELL)
80 output, not_used = p.communicate(); 78 output, not_used = p.communicate();
81 if output: 79 if output:
82 print output 80 print output
83 return output 81 return output
84 82
85 def time_cmd(cmd): 83 def time_cmd(cmd):
86 """Determine the amount of (real) time it takes to execute a given command.""" 84 """Determine the amount of (real) time it takes to execute a given command."""
87 start = time.time() 85 start = time.time()
88 run_cmd(cmd) 86 run_cmd(cmd)
89 return time.time() - start 87 return time.time() - start
90 88
91 def sync_and_build(): 89 def sync_and_build():
92 """Make sure we have the latest version of of the repo, and build it. We 90 """Make sure we have the latest version of of the repo, and build it. We
93 begin and end standing in DART_INSTALL_LOCATION. 91 begin and end standing in DART_INSTALL_LOCATION.
94 92
95 Returns: 93 Returns:
96 err_code = 1 if there was a problem building.""" 94 err_code = 1 if there was a problem building."""
97 os.chdir(DART_INSTALL_LOCATION) 95 os.chdir(DART_INSTALL_LOCATION)
98 #Revert our newly built minfrog to prevent conflicts when we update 96 #Revert our newly built minfrog to prevent conflicts when we update
99 run_cmd(['svn', 'revert', os.path.join(os.getcwd(), 'frog', 'minfrog')]) 97 run_cmd(['svn', 'revert', os.path.join(os.getcwd(), 'frog', 'minfrog')])
100 98
101 run_cmd(['gclient', 'sync']) 99 run_cmd(['gclient', 'sync'])
102 100
103 # On Windows, the output directory is marked as "Read Only," which causes an 101 # On Windows, the output directory is marked as "Read Only," which causes an
104 # error to be thrown when we use shutil.rmtree. This helper function changes 102 # error to be thrown when we use shutil.rmtree. This helper function changes
105 # the permissions so we can still delete the directory. 103 # the permissions so we can still delete the directory.
106 def on_rm_error(func, path, exc_info): 104 def on_rm_error(func, path, exc_info):
107 if os.path.exists(path): 105 if os.path.exists(path):
108 os.chmod(path, stat.S_IWRITE) 106 os.chmod(path, stat.S_IWRITE)
109 os.unlink(path) 107 os.unlink(path)
110 # TODO(efortuna): building the sdk locally is a band-aid until all build 108 # TODO(efortuna): building the sdk locally is a band-aid until all build
111 # platform SDKs are hosted in Google storage. Pull from https://sandbox. 109 # platform SDKs are hosted in Google storage. Pull from https://sandbox.
112 # google.com/storage/?arg=dart-dump-render-tree#dart-dump-render-tree%2Fsdk 110 # google.com/storage/?arg=dart-dump-render-tree#dart-dump-render-tree%2Fsdk
113 # eventually. 111 # eventually.
114 # TODO(efortuna): Currently always building ia32 architecture because we don't 112 # TODO(efortuna): Currently always building ia32 architecture because we don't
115 # have test statistics for what's passing on x64. Eliminate arch specification 113 # have test statistics for what's passing on x64. Eliminate arch specification
116 # when we have tests running on x64, too. 114 # when we have tests running on x64, too.
117 shutil.rmtree(os.path.join(os.getcwd(), 115 shutil.rmtree(os.path.join(os.getcwd(),
118 utils.GetBuildRoot(utils.GuessOS(), 'release', 'ia32')), 116 utils.GetBuildRoot(utils.GuessOS(), 'release', 'ia32')),
119 onerror=on_rm_error) 117 onerror=on_rm_error)
120 lines = run_cmd([os.path.join('.', 'tools', 'build.py'), '-m', 'release', 118 lines = run_cmd([os.path.join('.', 'tools', 'build.py'), '-m', 'release',
121 '--arch=ia32', 'create_sdk']) 119 '--arch=ia32', 'create_sdk'])
122 120
123 for line in lines: 121 for line in lines:
124 if 'BUILD FAILED' in lines: 122 if 'BUILD FAILED' in lines:
125 # Someone checked in a broken build! Just stop trying to make it work 123 # Someone checked in a broken build! Just stop trying to make it work
126 # and wait to try again. 124 # and wait to try again.
127 print 'Broken Build' 125 print 'Broken Build'
128 return 1 126 return 1
129 return 0 127 return 0
130 128
131 def ensure_output_directory(dir_name): 129 def ensure_output_directory(dir_name):
132 """Test that the listed directory name exists, and if not, create one for 130 """Test that the listed directory name exists, and if not, create one for
133 our output to be placed. 131 our output to be placed.
134 132
135 Args: 133 Args:
136 dir_name: the directory we will create if it does not exist.""" 134 dir_name: the directory we will create if it does not exist."""
137 dir_path = os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing', 135 dir_path = os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing',
138 'perf_testing', dir_name) 136 'perf_testing', dir_name)
139 if not os.path.exists(dir_path): 137 if not os.path.exists(dir_path):
140 os.mkdir(dir_path) 138 os.mkdir(dir_path)
141 print 'Creating output directory ', dir_path 139 print 'Creating output directory ', dir_path
142 140
143 def has_new_code(): 141 def has_new_code():
144 """Tests if there are any newer versions of files on the server.""" 142 """Tests if there are any newer versions of files on the server."""
145 os.chdir(DART_INSTALL_LOCATION) 143 os.chdir(DART_INSTALL_LOCATION)
146 results = run_cmd(['svn', 'st', '-u']) 144 results = run_cmd(['svn', 'st', '-u'])
147 for line in results: 145 for line in results:
148 if '*' in line: 146 if '*' in line:
149 return True 147 return True
150 return False 148 return False
151 149
152 def get_browsers(): 150 def get_browsers():
153 browsers = ['ff', 'chrome'] 151 browsers = ['ff', 'chrome']
154 if platform.system() == 'Darwin': 152 if platform.system() == 'Darwin':
155 browsers += ['safari'] 153 browsers += ['safari']
(...skipping 19 matching lines...) Expand all
175 return 'macos' 173 return 'macos'
176 else: 174 else:
177 return 'linux' 175 return 'linux'
178 176
179 def upload_to_app_engine(username, password): 177 def upload_to_app_engine(username, password):
180 """Upload our results to our appengine server. 178 """Upload our results to our appengine server.
181 Arguments: 179 Arguments:
182 username: App Engine username for uploading data to dartperf.googleplex.com 180 username: App Engine username for uploading data to dartperf.googleplex.com
183 password: App Engine password 181 password: App Engine password
184 """ 182 """
185 # TODO(efortuna): This is the most basic way to get the data up 183 # TODO(efortuna): This is the most basic way to get the data up
186 # for others to view. Revisit this once we're serving nicer graphs (Google 184 # for others to view. Revisit this once we're serving nicer graphs (Google
187 # Chart Tools) and from multiple perfbots and once we're in a position to 185 # Chart Tools) and from multiple perfbots and once we're in a position to
188 # organize the data in a useful manner(!!). 186 # organize the data in a useful manner(!!).
189 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing', 187 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing',
190 'perf_testing')) 188 'perf_testing'))
191 for data in [BROWSER_PERF, TIME_SIZE, CL_PERF]: 189 for data in [BROWSER_PERF, TIME_SIZE, CL_PERF]:
192 path = os.path.join('appengine', 'static', 'data', data, utils.GuessOS()) 190 path = os.path.join('appengine', 'static', 'data', data, utils.GuessOS())
193 shutil.rmtree(path, ignore_errors=True) 191 shutil.rmtree(path, ignore_errors=True)
194 os.makedirs(path) 192 os.makedirs(path)
195 files = [] 193 files = []
196 # Copy the 1000 most recent trace files to be uploaded. 194 # Copy the 1000 most recent trace files to be uploaded.
197 for f in os.listdir(data): 195 for f in os.listdir(data):
198 files += [(os.path.getmtime(os.path.join(data, f)), f)] 196 files += [(os.path.getmtime(os.path.join(data, f)), f)]
199 files.sort() 197 files.sort()
200 for f in files[-1000:]: 198 for f in files[-1000:]:
201 shutil.copyfile(os.path.join(data, f[1]), 199 shutil.copyfile(os.path.join(data, f[1]),
202 os.path.join(path, f[1]+'.txt')) 200 os.path.join(path, f[1]+'.txt'))
203 # Generate directory listing. 201 # Generate directory listing.
204 for data in [BROWSER_PERF, TIME_SIZE, CL_PERF]: 202 for data in [BROWSER_PERF, TIME_SIZE, CL_PERF]:
205 path = os.path.join('appengine', 'static', 'data', data, utils.GuessOS()) 203 path = os.path.join('appengine', 'static', 'data', data, utils.GuessOS())
206 out = open(os.path.join('appengine', 'static', 204 out = open(os.path.join('appengine', 'static',
207 '%s-%s.html' % (data, utils.GuessOS())), 'w') 205 '%s-%s.html' % (data, utils.GuessOS())), 'w')
208 out.write('<html>\n <body>\n <ul>\n') 206 out.write('<html>\n <body>\n <ul>\n')
209 for f in os.listdir(path): 207 for f in os.listdir(path):
210 if not f.startswith('.'): 208 if not f.startswith('.'):
211 out.write(' <li><a href=data' + \ 209 out.write(' <li><a href=data' + \
212 '''/%(data)s/%(os)s/%(file)s>%(file)s</a></li>\n''' % \ 210 '''/%(data)s/%(os)s/%(file)s>%(file)s</a></li>\n''' % \
213 {'data': data, 'os': utils.GuessOS(), 'file': f}) 211 {'data': data, 'os': utils.GuessOS(), 'file': f})
214 out.write(' </ul>\n </body>\n</html>') 212 out.write(' </ul>\n </body>\n</html>')
215 out.close() 213 out.close()
216 214
217 shutil.rmtree(os.path.join('appengine', 'static', 'graphs'), 215 shutil.rmtree(os.path.join('appengine', 'static', 'graphs'),
218 ignore_errors=True) 216 ignore_errors=True)
219 shutil.copytree('graphs', os.path.join('appengine', 'static', 'graphs')) 217 shutil.copytree('graphs', os.path.join('appengine', 'static', 'graphs'))
220 shutil.copyfile('index.html', os.path.join('appengine', 'static', 218 shutil.copyfile('index.html', os.path.join('appengine', 'static',
221 'index.html')) 219 'index.html'))
222 shutil.copyfile('data.html', os.path.join('appengine', 'static', 220 shutil.copyfile('data.html', os.path.join('appengine', 'static',
223 'data.html')) 221 'data.html'))
224 p = subprocess.Popen([os.path.join('..', '..', '..', 'third_party', 222 p = subprocess.Popen([os.path.join('..', '..', '..', 'third_party',
225 'appengine-python', 'appcfg.py'), 'update', 223 'appengine-python', 'appcfg.py'), 'update',
226 'appengine/'], shell=HAS_SHELL, stdin=subprocess.PIPE) 224 'appengine/'], shell=HAS_SHELL, stdin=subprocess.PIPE)
227 p.stdin.write(username + '\n') 225 p.stdin.write(username + '\n')
228 p.stdin.write(password + '\n') 226 p.stdin.write(password + '\n')
229 p.communicate() 227 p.communicate()
230 228
231 229
232 class TestRunner(object): 230 class TestRunner(object):
233 """The base class to provide shared code for different tests we will run and 231 """The base class to provide shared code for different tests we will run and
234 graph.""" 232 graph."""
235 233
236 def __init__(self, result_folder_name, platform_list, v8_and_or_frog_list, 234 def __init__(self, result_folder_name, platform_list, js_and_or_frog_list,
237 values_list): 235 values_list):
238 """Args: 236 """Args:
239 result_folder_name the name of the folder where a tracefile of 237 result_folder_name the name of the folder where a tracefile of
240 performance results will be stored. 238 performance results will be stored.
241 platform_list a list containing the platform(s) that our data has been 239 platform_list a list containing the platform(s) that our data has been
242 run on. (command line, firefox, chrome, etc) 240 run on. (command line, firefox, chrome, etc)
243 v8_and_or_frog_list a list specifying whether we hold data about Frog 241 js_and_or_frog_list a list specifying whether we hold data about Frog
244 generated code, plain JS code (v8), or a combination of both. 242 generated code, plain JS code (js), or a combination of both.
245 values_list a list containing the type of data we will be graphing 243 values_list a list containing the type of data we will be graphing
246 (benchmarks, percentage passing, etc)""" 244 (benchmarks, percentage passing, etc)"""
247 self.result_folder_name = result_folder_name 245 self.result_folder_name = result_folder_name
248 # cur_time is used as a timestamp of when this performance test was run. 246 # cur_time is used as a timestamp of when this performance test was run.
249 self.cur_time = str(time.mktime(datetime.datetime.now().timetuple())) 247 self.cur_time = str(time.mktime(datetime.datetime.now().timetuple()))
250 self.browser_color = {'chrome': 'green', 'ie': 'blue', 'ff': 'red', 248 self.browser_color = {'chrome': 'green', 'ie': 'blue', 'ff': 'red',
251 'safari':'black'} 249 'safari':'black'}
252 self.values_list = values_list 250 self.values_list = values_list
253 self.platform_list = platform_list 251 self.platform_list = platform_list
254 self.revision_dict = dict() 252 self.revision_dict = dict()
255 self.values_dict = dict() 253 self.values_dict = dict()
256 self.color_index = 0 254 self.color_index = 0
257 for platform in platform_list: 255 for platform in platform_list:
258 self.revision_dict[platform] = dict() 256 self.revision_dict[platform] = dict()
259 self.values_dict[platform] = dict() 257 self.values_dict[platform] = dict()
260 for f in v8_and_or_frog_list: 258 for f in js_and_or_frog_list:
261 self.revision_dict[platform][f] = dict() 259 self.revision_dict[platform][f] = dict()
262 self.values_dict[platform][f] = dict() 260 self.values_dict[platform][f] = dict()
263 for val in values_list: 261 for val in values_list:
264 self.revision_dict[platform][f][val] = [] 262 self.revision_dict[platform][f][val] = []
265 self.values_dict[platform][f][val] = [] 263 self.values_dict[platform][f][val] = []
266 if JS in v8_and_or_frog_list: 264 if JS in js_and_or_frog_list:
267 self.revision_dict[platform][JS][JS_MEAN] = [] 265 self.revision_dict[platform][JS][JS_MEAN] = []
268 self.values_dict[platform][JS][JS_MEAN] = [] 266 self.values_dict[platform][JS][JS_MEAN] = []
269 if FROG in v8_and_or_frog_list: 267 if FROG in js_and_or_frog_list:
270 self.revision_dict[platform][FROG][FROG_MEAN] = [] 268 self.revision_dict[platform][FROG][FROG_MEAN] = []
271 self.values_dict[platform][FROG][FROG_MEAN] = [] 269 self.values_dict[platform][FROG][FROG_MEAN] = []
272 270
273 def get_color(self): 271 def get_color(self):
274 color = COLORS[self.color_index] 272 color = COLORS[self.color_index]
275 self.color_index = (self.color_index + 1) % len(COLORS) 273 self.color_index = (self.color_index + 1) % len(COLORS)
276 return color 274 return color
277 275
278 def style_and_save_perf_plot(self, chart_title, y_axis_label, size_x, size_y, 276 def style_and_save_perf_plot(self, chart_title, y_axis_label, size_x, size_y,
279 legend_loc, filename, platform_list, v8_and_or_frog_list, values_list, 277 legend_loc, filename, platform_list, js_and_or_frog_list, values_list,
280 should_clear_axes=True): 278 should_clear_axes=True):
281 """Sets style preferences for chart boilerplate that is consistent across 279 """Sets style preferences for chart boilerplate that is consistent across
282 all charts, and saves the chart as a png. 280 all charts, and saves the chart as a png.
283 281
284 Args: 282 Args:
285 size_x: the size of the printed chart, in inches, in the horizontal 283 size_x: the size of the printed chart, in inches, in the horizontal
286 direction 284 direction
287 size_y: the size of the printed chart, in inches in the vertical direction 285 size_y: the size of the printed chart, in inches in the vertical direction
288 legend_loc: the location of the legend in on the chart. See suitable 286 legend_loc: the location of the legend in on the chart. See suitable
289 arguments for the loc argument in matplotlib 287 arguments for the loc argument in matplotlib
290 filename: the filename that we want to save the resulting chart as 288 filename: the filename that we want to save the resulting chart as
291 platform_list: a list containing the platform(s) that our data has been 289 platform_list: a list containing the platform(s) that our data has been
292 run on. (command line, firefox, chrome, etc) 290 run on. (command line, firefox, chrome, etc)
293 values_list: a list containing the type of data we will be graphing 291 values_list: a list containing the type of data we will be graphing
294 (performance, percentage passing, etc) 292 (performance, percentage passing, etc)
295 should_clear_axes: True if we want to create a fresh graph, instead of 293 should_clear_axes: True if we want to create a fresh graph, instead of
296 plotting additional lines on the current graph.""" 294 plotting additional lines on the current graph."""
297 if should_clear_axes: 295 if should_clear_axes:
298 plt.cla() # cla = clear current axes 296 plt.cla() # cla = clear current axes
299 for platform in platform_list: 297 for platform in platform_list:
300 for f in v8_and_or_frog_list: 298 for f in js_and_or_frog_list:
301 for val in values_list: 299 for val in values_list:
302 plt.plot(self.revision_dict[platform][f][val], 300 plt.plot(self.revision_dict[platform][f][val],
303 self.values_dict[platform][f][val], 301 self.values_dict[platform][f][val],
304 color=self.get_color(), label='%s-%s-%s' % (platform, f, val)) 302 color=self.get_color(), label='%s-%s-%s' % (platform, f, val))
305 303
306 plt.xlabel('Revision Number') 304 plt.xlabel('Revision Number')
307 plt.ylabel(y_axis_label) 305 plt.ylabel(y_axis_label)
308 plt.title(chart_title) 306 plt.title(chart_title)
309 fontP = FontProperties() 307 fontP = FontProperties()
310 fontP.set_size('small') 308 fontP.set_size('small')
311 plt.legend(loc=legend_loc, prop = fontP) 309 plt.legend(loc=legend_loc, prop = fontP)
312 310
313 fig = plt.gcf() 311 fig = plt.gcf()
314 fig.set_size_inches(size_x, size_y) 312 fig.set_size_inches(size_x, size_y)
315 fig.savefig(os.path.join(GRAPH_OUT_DIR, filename)) 313 fig.savefig(os.path.join(GRAPH_OUT_DIR, filename))
316 314
317 def add_svn_revision_to_trace(self, outfile): 315 def add_svn_revision_to_trace(self, outfile):
318 """Add the svn version number to the provided tracefile.""" 316 """Add the svn version number to the provided tracefile."""
319 def search_for_revision(svn_info_command): 317 def search_for_revision(svn_info_command):
320 p = subprocess.Popen(svn_info_command, stdout = subprocess.PIPE, 318 p = subprocess.Popen(svn_info_command, stdout = subprocess.PIPE,
321 stderr = subprocess.STDOUT, shell = HAS_SHELL) 319 stderr = subprocess.STDOUT, shell = HAS_SHELL)
322 output, _ = p.communicate() 320 output, _ = p.communicate()
323 for line in output.split('\n'): 321 for line in output.split('\n'):
324 if 'Revision' in line: 322 if 'Revision' in line:
325 run_cmd(['echo', line.strip()], outfile) 323 run_cmd(['echo', line.strip()], outfile)
326 return True 324 return True
327 return False 325 return False
328 326
329 if not search_for_revision(['svn', 'info']): 327 if not search_for_revision(['svn', 'info']):
330 if not search_for_revision(['git', 'svn', 'info']): 328 if not search_for_revision(['git', 'svn', 'info']):
331 run_cmd(['echo', 'Revision: unknown'], outfile) 329 run_cmd(['echo', 'Revision: unknown'], outfile)
332 330
333 def calculate_geometric_mean(self, platform, frog_or_v8, svn_revision): 331 def calculate_geometric_mean(self, platform, frog_or_js, svn_revision):
334 """Calculate the aggregate geometric mean for JS and frog benchmark sets, 332 """Calculate the aggregate geometric mean for JS and frog benchmark sets,
335 given two benchmark dictionaries.""" 333 given two benchmark dictionaries."""
336 geo_mean = 0 334 geo_mean = 0
337 for benchmark in get_benchmarks(): 335 for benchmark in get_benchmarks():
338 geo_mean += math.log(self.values_dict[platform][frog_or_v8][benchmark][ 336 geo_mean += math.log(self.values_dict[platform][frog_or_js][benchmark][
339 len(self.values_dict[platform][frog_or_v8][benchmark]) - 1]) 337 len(self.values_dict[platform][frog_or_js][benchmark]) - 1])
340 338
341 mean = JS_MEAN 339 mean = JS_MEAN
342 if frog_or_v8 == FROG: 340 if frog_or_js == FROG:
343 mean = FROG_MEAN 341 mean = FROG_MEAN
344 self.values_dict[platform][frog_or_v8][mean] += \ 342 self.values_dict[platform][frog_or_js][mean] += \
345 [math.pow(math.e, geo_mean / len(get_benchmarks()))] 343 [math.pow(math.e, geo_mean / len(get_benchmarks()))]
346 self.revision_dict[platform][frog_or_v8][mean] += [svn_revision] 344 self.revision_dict[platform][frog_or_js][mean] += [svn_revision]
347 345
348 def run(self): 346 def run(self):
349 """Run the benchmarks/tests from the command line and plot the 347 """Run the benchmarks/tests from the command line and plot the
350 results.""" 348 results."""
351 plt.cla() # cla = clear current axes 349 plt.cla() # cla = clear current axes
352 os.chdir(DART_INSTALL_LOCATION) 350 os.chdir(DART_INSTALL_LOCATION)
353 ensure_output_directory(self.result_folder_name) 351 ensure_output_directory(self.result_folder_name)
354 ensure_output_directory(GRAPH_OUT_DIR) 352 ensure_output_directory(GRAPH_OUT_DIR)
355 self.run_tests() 353 self.run_tests()
356 354
357 os.chdir(os.path.join('tools', 'testing', 'perf_testing')) 355 os.chdir(os.path.join('tools', 'testing', 'perf_testing'))
358 356
359 # TODO(efortuna): You will want to make this only use a subset of the files 357 # TODO(efortuna): You will want to make this only use a subset of the files
360 # eventually. 358 # eventually.
361 files = os.listdir(self.result_folder_name) 359 files = os.listdir(self.result_folder_name)
362 360
363 for afile in files: 361 for afile in files:
364 if not afile.startswith('.'): 362 if not afile.startswith('.'):
365 self.process_file(afile) 363 self.process_file(afile)
366 364
367 self.plot_results('%s.png' % self.result_folder_name) 365 self.plot_results('%s.png' % self.result_folder_name)
368 366
369 class PerformanceTest(TestRunner): 367 class PerformanceTest(TestRunner):
370 """Super class for all performance testing.""" 368 """Super class for all performance testing."""
371 def __init__(self, result_folder_name, platform_list, platform_type): 369 def __init__(self, result_folder_name, platform_list, platform_type):
372 super(PerformanceTest, self).__init__(result_folder_name, 370 super(PerformanceTest, self).__init__(result_folder_name,
373 platform_list, get_versions(), get_benchmarks()) 371 platform_list, get_versions(), get_benchmarks())
374 self.platform_list = platform_list 372 self.platform_list = platform_list
375 self.platform_type = platform_type 373 self.platform_type = platform_type
376 374
377 def plot_all_perf(self, png_filename): 375 def plot_all_perf(self, png_filename):
378 """Create a plot that shows the performance changes of individual benchmarks 376 """Create a plot that shows the performance changes of individual benchmarks
379 run by JS and generated by frog, over svn history.""" 377 run by JS and generated by frog, over svn history."""
380 for benchmark in get_benchmarks(): 378 for benchmark in get_benchmarks():
381 self.style_and_save_perf_plot( 379 self.style_and_save_perf_plot(
382 'Performance of %s over time on the %s on %s' % (benchmark, 380 'Performance of %s over time on the %s on %s' % (benchmark,
383 self.platform_type, utils.GuessOS()), 'Speed (bigger = better)', 16, 381 self.platform_type, utils.GuessOS()), 'Speed (bigger = better)', 16,
384 14, 'lower left', benchmark + png_filename, self.platform_list, 382 14, 'lower left', benchmark + png_filename, self.platform_list,
385 get_versions(), [benchmark]) 383 get_versions(), [benchmark])
386 384
387 def plot_avg_perf(self, png_filename): 385 def plot_avg_perf(self, png_filename):
388 """Generate a plot that shows the performance changes of the geomentric mean 386 """Generate a plot that shows the performance changes of the geomentric mean
389 of JS and frog benchmark performance over svn history.""" 387 of JS and frog benchmark performance over svn history."""
390 (title, y_axis, size_x, size_y, loc, filename) = \ 388 (title, y_axis, size_x, size_y, loc, filename) = \
391 ('Geometric Mean of benchmark %s performance on %s ' % 389 ('Geometric Mean of benchmark %s performance on %s ' %
392 (self.platform_type, utils.GuessOS()), 'Speed (bigger = better)', 16, 5, 390 (self.platform_type, utils.GuessOS()), 'Speed (bigger = better)', 16, 5,
393 'lower left', 'avg'+png_filename) 391 'lower left', 'avg'+png_filename)
394 clear_axis = True 392 clear_axis = True
395 for platform in self.platform_list: 393 for platform in self.platform_list:
396 self.style_and_save_perf_plot(title, y_axis, size_x, size_y, loc, 394 self.style_and_save_perf_plot(title, y_axis, size_x, size_y, loc,
397 filename, [platform], [JS], [JS_MEAN], clear_axis) 395 filename, [platform], [JS], [JS_MEAN], clear_axis)
398 clear_axis = False 396 clear_axis = False
399 self.style_and_save_perf_plot(title, y_axis, size_x, size_y, loc, 397 self.style_and_save_perf_plot(title, y_axis, size_x, size_y, loc,
400 filename, [platform], [FROG], [FROG_MEAN], clear_axis) 398 filename, [platform], [FROG], [FROG_MEAN], clear_axis)
401 399
402 def plot_results(self, png_filename): 400 def plot_results(self, png_filename):
403 self.plot_all_perf(png_filename) 401 self.plot_all_perf(png_filename)
404 self.plot_avg_perf('2' + png_filename) 402 self.plot_avg_perf('2' + png_filename)
405 403
406 404
407 class CommandLinePerformanceTest(PerformanceTest): 405 class CommandLinePerformanceTest(PerformanceTest):
408 """Run performance tests from the command line.""" 406 """Run performance tests from the command line."""
409 407
410 def __init__(self, result_folder_name): 408 def __init__(self, result_folder_name):
411 super(CommandLinePerformanceTest, self).__init__(result_folder_name, 409 super(CommandLinePerformanceTest, self).__init__(result_folder_name,
412 [COMMAND_LINE], 'command line') 410 [COMMAND_LINE], 'command line')
413 411
414 def process_file(self, afile): 412 def process_file(self, afile):
415 """Pull all the relevant information out of a given tracefile. 413 """Pull all the relevant information out of a given tracefile.
416 414
417 Args: 415 Args:
418 afile: The filename string we will be processing.""" 416 afile: The filename string we will be processing."""
419 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing', 417 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing',
420 'perf_testing')) 418 'perf_testing'))
421 f = open(os.path.join(self.result_folder_name, afile)) 419 f = open(os.path.join(self.result_folder_name, afile))
422 tabulate_data = False 420 tabulate_data = False
423 revision_num = 0 421 revision_num = 0
424 for line in f.readlines(): 422 for line in f.readlines():
425 if 'Revision' in line: 423 if 'Revision' in line:
426 revision_num = int(line.split()[1]) 424 revision_num = int(line.split()[1])
427 elif 'Benchmark' in line: 425 elif 'Benchmark' in line:
428 tabulate_data = True 426 tabulate_data = True
429 elif tabulate_data: 427 elif tabulate_data:
430 tokens = line.split() 428 tokens = line.split()
431 if len(tokens) < 4 or tokens[0] not in get_benchmarks(): 429 if len(tokens) < 4 or tokens[0] not in get_benchmarks():
432 #Done tabulating data. 430 #Done tabulating data.
433 break 431 break
434 v8_value = float(tokens[1]) 432 js_value = float(tokens[1])
435 frog_value = float(tokens[3]) 433 frog_value = float(tokens[3])
436 if v8_value == 0 or frog_value == 0: 434 if js_value == 0 or frog_value == 0:
437 #Then there was an error when this performance test was run. Do not 435 #Then there was an error when this performance test was run. Do not
438 #count it in our numbers. 436 #count it in our numbers.
439 return 437 return
440 benchmark = tokens[0] 438 benchmark = tokens[0]
441 self.revision_dict[COMMAND_LINE][JS][benchmark] += [revision_num] 439 self.revision_dict[COMMAND_LINE][JS][benchmark] += [revision_num]
442 self.values_dict[COMMAND_LINE][JS][benchmark] += [v8_value] 440 self.values_dict[COMMAND_LINE][JS][benchmark] += [js_value]
443 self.revision_dict[COMMAND_LINE][FROG][benchmark] += [revision_num] 441 self.revision_dict[COMMAND_LINE][FROG][benchmark] += [revision_num]
444 self.values_dict[COMMAND_LINE][FROG][benchmark] += [frog_value] 442 self.values_dict[COMMAND_LINE][FROG][benchmark] += [frog_value]
445 f.close() 443 f.close()
446 444
447 self.calculate_geometric_mean(COMMAND_LINE, FROG, revision_num) 445 self.calculate_geometric_mean(COMMAND_LINE, FROG, revision_num)
448 self.calculate_geometric_mean(COMMAND_LINE, JS, revision_num) 446 self.calculate_geometric_mean(COMMAND_LINE, JS, revision_num)
449 447
450 def run_tests(self): 448 def run_tests(self):
451 """Run a performance test on our updated system.""" 449 """Run a performance test on our updated system."""
452 os.chdir('frog') 450 os.chdir('frog')
453 self.trace_file = os.path.join('..', 'tools', 'testing', 'perf_testing', 451 self.trace_file = os.path.join('..', 'tools', 'testing', 'perf_testing',
454 self.result_folder_name, 'result' + self.cur_time) 452 self.result_folder_name, 'result' + self.cur_time)
455 run_cmd(['python', os.path.join('benchmarks', 'perf_tests.py')], 453 run_cmd(['python', os.path.join('benchmarks', 'perf_tests.py')],
456 self.trace_file) 454 self.trace_file)
457 os.chdir('..') 455 os.chdir('..')
458 456
459 457
460 class BrowserPerformanceTest(PerformanceTest): 458 class BrowserPerformanceTest(PerformanceTest):
461 """Runs performance tests, in the browser.""" 459 """Runs performance tests, in the browser."""
462 460
463 def __init__(self, result_folder_name): 461 def __init__(self, result_folder_name):
464 super(BrowserPerformanceTest, self).__init__( 462 super(BrowserPerformanceTest, self).__init__(
465 result_folder_name, get_browsers(), 'browser') 463 result_folder_name, get_browsers(), 'browser')
466 464
467 def run_tests(self): 465 def run_tests(self):
468 """Run a performance test in the browser.""" 466 """Run a performance test in the browser."""
469 467
470 os.chdir('frog') 468 os.chdir('frog')
471 run_cmd(['python', os.path.join('benchmarks', 'make_web_benchmarks.py')]) 469 run_cmd(['python', os.path.join('benchmarks', 'make_web_benchmarks.py')])
472 os.chdir('..') 470 os.chdir('..')
473 471
474 for browser in get_browsers(): 472 for browser in get_browsers():
475 for version in get_versions(): 473 for version in get_versions():
476 self.trace_file = os.path.join('tools', 'testing', 'perf_testing', 474 self.trace_file = os.path.join('tools', 'testing', 'perf_testing',
477 self.result_folder_name, 475 self.result_folder_name,
478 'perf-%s-%s-%s' % (self.cur_time, browser, version)) 476 'perf-%s-%s-%s' % (self.cur_time, browser, version))
479 self.add_svn_revision_to_trace(self.trace_file) 477 self.add_svn_revision_to_trace(self.trace_file)
480 file_path = os.path.join(os.getcwd(), 'internal', 'browserBenchmarks', 478 file_path = os.path.join(os.getcwd(), 'internal', 'browserBenchmarks',
481 'benchmark_page_%s.html' % version) 479 'benchmark_page_%s.html' % version)
482 run_cmd(['python', os.path.join('tools', 'testing', 'run_selenium.py'), 480 run_cmd(['python', os.path.join('tools', 'testing', 'run_selenium.py'),
483 '--out', file_path, '--browser', browser, 481 '--out', file_path, '--browser', browser,
484 '--timeout', '600', '--perf'], self.trace_file, append=True) 482 '--timeout', '600', '--perf'], self.trace_file, append=True)
485 483
486 def process_file(self, afile): 484 def process_file(self, afile):
487 """Comb through the html to find the performance results.""" 485 """Comb through the html to find the performance results."""
488 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing', 486 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing',
489 'perf_testing')) 487 'perf_testing'))
490 parts = afile.split('-') 488 parts = afile.split('-')
491 browser = parts[2] 489 browser = parts[2]
492 version = parts[3] 490 version = parts[3]
493 f = open(os.path.join(self.result_folder_name, afile)) 491 f = open(os.path.join(self.result_folder_name, afile))
494 lines = f.readlines() 492 lines = f.readlines()
495 line = '' 493 line = ''
496 i = 0 494 i = 0
497 revision_num = 0 495 revision_num = 0
498 while '<div id="results">' not in line and i < len(lines): 496 while '<div id="results">' not in line and i < len(lines):
499 if 'Revision' in line: 497 if 'Revision' in line:
500 revision_num = int(line.split()[1].strip('"')) 498 revision_num = int(line.split()[1].strip('"'))
501 line = lines[i] 499 line = lines[i]
502 i += 1 500 i += 1
503 501
504 if i >= len(lines) or revision_num == 0: 502 if i >= len(lines) or revision_num == 0:
505 # Then this run did not complete. Ignore this tracefile. 503 # Then this run did not complete. Ignore this tracefile.
506 return 504 return
507 505
508 line = lines[i] 506 line = lines[i]
509 i += 1 507 i += 1
510 results = [] 508 results = []
511 if line.find('<br>') > -1: 509 if line.find('<br>') > -1:
512 results = line.split('<br>') 510 results = line.split('<br>')
513 else: 511 else:
514 results = line.split('<br />') 512 results = line.split('<br />')
515 for result in results: 513 for result in results:
516 name_and_score = result.split(':') 514 name_and_score = result.split(':')
517 if len(name_and_score) < 2: 515 if len(name_and_score) < 2:
518 break 516 break
519 name = name_and_score[0].strip() 517 name = name_and_score[0].strip()
520 score = name_and_score[1].strip() 518 score = name_and_score[1].strip()
521 if version == JS or version == 'v8': 519 if version == JS or version == 'v8':
522 version = JS 520 version = JS
523 bench_dict = self.values_dict[browser][JS] 521 bench_dict = self.values_dict[browser][JS]
524 else: 522 else:
525 bench_dict = self.values_dict[browser][FROG] 523 bench_dict = self.values_dict[browser][FROG]
526 bench_dict[name] += [float(score)] 524 bench_dict[name] += [float(score)]
527 self.revision_dict[browser][version][name] += [revision_num] 525 self.revision_dict[browser][version][name] += [revision_num]
528 526
529 f.close() 527 f.close()
530 self.calculate_geometric_mean(browser, version, revision_num) 528 self.calculate_geometric_mean(browser, version, revision_num)
531 529
532
533 class BrowserCorrectnessTest(TestRunner):
534 def __init__(self, test_type, result_folder_name):
535 super(BrowserCorrectnessTest, self).__init__(result_folder_name,
536 get_browsers(), [FROG], [CORRECTNESS])
537 self.test_type = test_type
538
539 def run_tests(self):
540 """Run a test of the latest svn revision."""
541 system = get_os_directory()
542 suffix = ''
543 if platform.system() == 'Windows':
544 suffix = '.exe'
545 for browser in get_browsers():
546 current_file = 'correctness%s-%s' % (self.cur_time, browser)
547 self.trace_file = os.path.join('tools', 'testing',
548 'perf_testing', self.result_folder_name, current_file)
549 self.add_svn_revision_to_trace(self.trace_file)
550 dart_sdk = os.path.join(os.getcwd(), utils.GetBuildRoot(utils.GuessOS(),
551 'release', 'ia32'), 'dart-sdk')
552 run_cmd([os.path.join('.', 'tools', 'testing', 'bin', system,
553 'dart' + suffix), os.path.join('tools', 'test.dart'),
554 '--compiler=frog', '--runtime=%s' % browser,
555 '--frog=%s' % os.path.join(dart_sdk, 'bin',
556 'frogc'), '--froglib=%s' % os.path.join(dart_sdk, 'lib'), '--report',
557 '--timeout=20', '--progress=color', '--mode=release',
558 self.test_type], self.trace_file, append=True)
559
560 def process_file(self, afile):
561 """Given a trace file, extract all the relevant information out of it to
562 determine the number of correctly passing tests.
563
564 Arguments:
565 afile: the filename string"""
566 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing',
567 'perf_testing'))
568 browser = afile.rpartition('-')[2]
569 f = open(os.path.join(self.result_folder_name, afile))
570 revision_num = 0
571 lines = f.readlines()
572 total_tests = 0
573 num_failed = 0
574 expect_fail = 0
575 for line in lines:
576 if 'Total:' in line:
577 total_tests = int(line.split('Total: ')[1].split()[0])
578 if 'will be skipped' in line:
579 total_tests -= int(line.split()[1])
580 if 'we should fix' in line:
581 expect_fail += int(line.split()[1])
582 if 'Revision' in line:
583 revision_num = int(line.split()[1])
584 if '--- TIMEOUT ---' in line or 'FAIL:' in line or 'PASS' in line:
585 # (A printed out 'PASS' indicates we incorrectly passed a negative
586 # test.)
587 num_failed += 1
588
589 self.revision_dict[browser][FROG][CORRECTNESS] += [revision_num]
590 self.values_dict[browser][FROG][CORRECTNESS] += [100.0 *
591 (((float)(total_tests - (expect_fail + num_failed))) /total_tests)]
592 f.close()
593
594 def plot_results(self, png_filename):
595 first_time = True
596 for browser in get_browsers():
597 self.style_and_save_perf_plot('Percentage of language tests passing in '
598 'different browsers', '% of tests passed', 8, 8, 'lower left',
599 png_filename, [browser], [FROG], [CORRECTNESS], first_time)
600 first_time = False
601
602 530
603 class CompileTimeAndSizeTest(TestRunner): 531 class CompileTimeAndSizeTest(TestRunner):
604 """Run tests to determine how long minfrog takes to compile, and the compiled 532 """Run tests to determine how long minfrog takes to compile, and the compiled
605 file output size of some benchmarking files.""" 533 file output size of some benchmarking files."""
606 def __init__(self, result_folder_name): 534 def __init__(self, result_folder_name):
607 super(CompileTimeAndSizeTest, self).__init__(result_folder_name, 535 super(CompileTimeAndSizeTest, self).__init__(result_folder_name,
608 [COMMAND_LINE], [FROG], ['Compiling on Dart VM', 'Bootstrapping', 536 [COMMAND_LINE], [FROG], ['Compiling on Dart VM', 'Bootstrapping',
609 'minfrog', 'swarm', 'total']) 537 'minfrog', 'swarm', 'total'])
610 self.failure_threshold = {'Compiling on Dart VM' : 1, 'Bootstrapping' : .5, 538 self.failure_threshold = {'Compiling on Dart VM' : 1, 'Bootstrapping' : .5,
611 'minfrog' : 100, 'swarm' : 100, 'total' : 100} 539 'minfrog' : 100, 'swarm' : 100, 'total' : 100}
612 540
613 def run_tests(self): 541 def run_tests(self):
614 os.chdir('frog') 542 os.chdir('frog')
615 self.trace_file = os.path.join('..', 'tools', 'testing', 'perf_testing', 543 self.trace_file = os.path.join('..', 'tools', 'testing', 'perf_testing',
616 self.result_folder_name, self.result_folder_name + self.cur_time) 544 self.result_folder_name, self.result_folder_name + self.cur_time)
617 545
618 self.add_svn_revision_to_trace(self.trace_file) 546 self.add_svn_revision_to_trace(self.trace_file)
619 547
620 suffix = '' 548 suffix = ''
621 if platform.system() == 'Windows': 549 if platform.system() == 'Windows':
622 suffix = '.exe' 550 suffix = '.exe'
623 elapsed = time_cmd([os.path.join('..', utils.GetBuildRoot(utils.GuessOS(), 551 elapsed = time_cmd([os.path.join('..', utils.GetBuildRoot(utils.GuessOS(),
624 'release', 'ia32'), 'dart' + suffix), os.path.join('.', 'minfrogc.dart'), 552 'release', 'ia32'), 'dart' + suffix), os.path.join('.', 'minfrogc.dart'),
625 '--out=minfrog', 'minfrog.dart']) 553 '--out=minfrog', 'minfrog.dart'])
626 run_cmd(['echo', '%f Compiling on Dart VM in production mode in seconds' 554 run_cmd(['echo', '%f Compiling on Dart VM in production mode in seconds'
627 % elapsed], self.trace_file, append=True) 555 % elapsed], self.trace_file, append=True)
628 elapsed = time_cmd([os.path.join('.', 'minfrog'), '--out=minfrog', 556 elapsed = time_cmd([os.path.join('.', 'minfrog'), '--out=minfrog',
629 'minfrog.dart', os.path.join('tests', 'hello.dart')]) 557 'minfrog.dart', os.path.join('tests', 'hello.dart')])
630 if elapsed < self.failure_threshold['Bootstrapping']: 558 if elapsed < self.failure_threshold['Bootstrapping']:
631 #minfrog didn't compile correctly. Stop testing now, because subsequent 559 #minfrog didn't compile correctly. Stop testing now, because subsequent
632 #numbers will be meaningless. 560 #numbers will be meaningless.
633 return 561 return
634 size = os.path.getsize('minfrog') 562 size = os.path.getsize('minfrog')
635 run_cmd(['echo', '%f Bootstrapping time in seconds in production mode' % 563 run_cmd(['echo', '%f Bootstrapping time in seconds in production mode' %
636 elapsed], self.trace_file, append=True) 564 elapsed], self.trace_file, append=True)
637 run_cmd(['echo', '%d Generated checked minfrog size' % size], 565 run_cmd(['echo', '%d Generated checked minfrog size' % size],
638 self.trace_file, append=True) 566 self.trace_file, append=True)
639 567
640 run_cmd([os.path.join('.', 'minfrog'), '--out=swarm-result', 568 run_cmd([os.path.join('.', 'minfrog'), '--out=swarm-result',
641 '--compile-only', os.path.join('..', 'samples', 'swarm', 569 '--compile-only', os.path.join('..', 'samples', 'swarm',
642 'swarm.dart')]) 570 'swarm.dart')])
643 swarm_size = 0 571 swarm_size = 0
644 try: 572 try:
645 swarm_size = os.path.getsize('swarm-result') 573 swarm_size = os.path.getsize('swarm-result')
646 except OSError: 574 except OSError:
647 pass #If compilation failed, continue on running other tests. 575 pass #If compilation failed, continue on running other tests.
648 576
649 run_cmd([os.path.join('.', 'minfrog'), '--out=total-result', 577 run_cmd([os.path.join('.', 'minfrog'), '--out=total-result',
650 '--compile-only', os.path.join('..', 'samples', 'total', 578 '--compile-only', os.path.join('..', 'samples', 'total',
651 'client', 'Total.dart')]) 579 'client', 'Total.dart')])
652 total_size = 0 580 total_size = 0
653 try: 581 try:
654 total_size = os.path.getsize('total-result') 582 total_size = os.path.getsize('total-result')
655 except OSError: 583 except OSError:
656 pass #If compilation failed, continue on running other tests. 584 pass #If compilation failed, continue on running other tests.
657 585
658 run_cmd(['echo', '%d Generated checked swarm size' % swarm_size], 586 run_cmd(['echo', '%d Generated checked swarm size' % swarm_size],
659 self.trace_file, append=True) 587 self.trace_file, append=True)
660 588
661 run_cmd(['echo', '%d Generated checked total size' % total_size], 589 run_cmd(['echo', '%d Generated checked total size' % total_size],
662 self.trace_file, append=True) 590 self.trace_file, append=True)
663 os.chdir('..') 591 os.chdir('..')
664 592
665 def process_file(self, afile): 593 def process_file(self, afile):
666 """Pull all the relevant information out of a given tracefile. 594 """Pull all the relevant information out of a given tracefile.
667 595
668 Args: 596 Args:
669 afile: is the filename string we will be processing.""" 597 afile: is the filename string we will be processing."""
670 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing', 598 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing',
671 'perf_testing')) 599 'perf_testing'))
672 f = open(os.path.join(self.result_folder_name, afile)) 600 f = open(os.path.join(self.result_folder_name, afile))
673 tabulate_data = False 601 tabulate_data = False
674 revision_num = 0 602 revision_num = 0
675 for line in f.readlines(): 603 for line in f.readlines():
676 tokens = line.split() 604 tokens = line.split()
677 if 'Revision' in line: 605 if 'Revision' in line:
678 revision_num = int(line.split()[1]) 606 revision_num = int(line.split()[1])
679 else: 607 else:
680 for metric in self.values_list: 608 for metric in self.values_list:
681 if metric in line: 609 if metric in line:
682 num = tokens[0] 610 num = tokens[0]
683 if num.find('.') == -1: 611 if num.find('.') == -1:
684 num = int(num) 612 num = int(num)
685 else: 613 else:
686 num = float(num) 614 num = float(num)
687 self.values_dict[COMMAND_LINE][FROG][metric] += [num] 615 self.values_dict[COMMAND_LINE][FROG][metric] += [num]
688 self.revision_dict[COMMAND_LINE][FROG][metric] += [revision_num] 616 self.revision_dict[COMMAND_LINE][FROG][metric] += [revision_num]
689 617
690 if revision_num != 0: 618 if revision_num != 0:
691 for metric in self.values_list: 619 for metric in self.values_list:
692 self.revision_dict[COMMAND_LINE][FROG][metric].pop() 620 self.revision_dict[COMMAND_LINE][FROG][metric].pop()
693 self.revision_dict[COMMAND_LINE][FROG][metric] += [revision_num] 621 self.revision_dict[COMMAND_LINE][FROG][metric] += [revision_num]
694 # Fill in 0 if compilation failed. 622 # Fill in 0 if compilation failed.
695 if self.values_dict[COMMAND_LINE][FROG][metric][-1] < \ 623 if self.values_dict[COMMAND_LINE][FROG][metric][-1] < \
696 self.failure_threshold[metric]: 624 self.failure_threshold[metric]:
697 self.values_dict[COMMAND_LINE][FROG][metric] += [0] 625 self.values_dict[COMMAND_LINE][FROG][metric] += [0]
698 self.revision_dict[COMMAND_LINE][FROG][metric] += [revision_num] 626 self.revision_dict[COMMAND_LINE][FROG][metric] += [revision_num]
699 627
700 f.close() 628 f.close()
701 629
702 def plot_results(self, png_filename): 630 def plot_results(self, png_filename):
703 self.style_and_save_perf_plot('Compiled minfrog Sizes', 631 self.style_and_save_perf_plot('Compiled minfrog Sizes',
704 'Size (in bytes)', 10, 10, 'lower left', png_filename, [COMMAND_LINE], 632 'Size (in bytes)', 10, 10, 'lower left', png_filename, [COMMAND_LINE],
705 [FROG], ['swarm', 'total', 'minfrog']) 633 [FROG], ['swarm', 'total', 'minfrog'])
706 634
707 self.style_and_save_perf_plot('Time to compile and bootstrap', 635 self.style_and_save_perf_plot('Time to compile and bootstrap',
708 'Seconds', 10, 10, 'lower left', '2' + png_filename, [COMMAND_LINE], 636 'Seconds', 10, 10, 'lower left', '2' + png_filename, [COMMAND_LINE],
709 [FROG], ['Bootstrapping', 'Compiling on Dart VM']) 637 [FROG], ['Bootstrapping', 'Compiling on Dart VM'])
710 638
711 def parse_args(): 639 def parse_args():
712 parser = optparse.OptionParser() 640 parser = optparse.OptionParser()
713 parser.add_option('--command-line', '-c', dest='cl', 641 parser.add_option('--command-line', '-c', dest='cl',
714 help='Run the command line tests', 642 help='Run the command line tests',
715 action='store_true', default=False)
716 parser.add_option('--size-time', '-s', dest='size',
717 help='Run the code size and timing tests',
718 action='store_true', default=False) 643 action='store_true', default=False)
719 parser.add_option('--language', '-l', dest='language', 644 parser.add_option('--size-time', '-s', dest='size',
720 help='Run the language correctness tests', 645 help='Run the code size and timing tests',
721 action='store_true', default=False) 646 action='store_true', default=False)
722 parser.add_option('--browser-perf', '-b', dest='perf', 647 parser.add_option('--browser-perf', '-b', dest='perf',
723 help='Run the browser performance tests', 648 help='Run the browser performance tests',
724 action='store_true', default=False) 649 action='store_true', default=False)
725 parser.add_option('--forever', '-f', dest='continuous', 650 parser.add_option('--forever', '-f', dest='continuous',
726 help = 'Run this script forever, always checking for the next svn ' 651 help = 'Run this script forever, always checking for the next svn '
727 'checkin', action='store_true', default=False) 652 'checkin', action='store_true', default=False)
728 parser.add_option('--verbose', '-v', dest='verbose', 653 parser.add_option('--verbose', '-v', dest='verbose',
729 help = 'Print extra debug output', action='store_true', default=False) 654 help = 'Print extra debug output', action='store_true', default=False)
730 parser.add_option('--user', '-u', dest='username', 655 parser.add_option('--user', '-u', dest='username',
731 help='Username for submitting new data to App Engine', default='') 656 help='Username for submitting new data to App Engine', default='')
732 657
733 args, ignored = parser.parse_args() 658 args, ignored = parser.parse_args()
734 password = '' 659 password = ''
735 if args.username != '': 660 if args.username != '':
736 password = getpass.getpass("App Engine Password: ") 661 password = getpass.getpass("App Engine Password: ")
737 else: 662 else:
738 print 'Warning: performance data will not be uploaded to App Engine' + \ 663 print 'Warning: performance data will not be uploaded to App Engine' + \
739 ' if you do not provide a username.' 664 ' if you do not provide a username.'
740 if not (args.cl or args.size or args.language or args.perf): 665 if not (args.cl or args.size or args.perf):
741 args.cl = args.size = args.language = args.perf = True 666 args.cl = args.size = args.perf = True
742 return (args.cl, args.size, args.language, args.perf, args.continuous, 667 return (args.cl, args.size, args.perf, args.continuous,
743 args.verbose, args.username, password) 668 args.verbose, args.username, password)
744 669
745 def run_test_sequence(cl, size, language, perf, username, password): 670 def run_test_sequence(cl, size, perf, username, password):
746 # The buildbot already builds and syncs to a specific revision. Don't fight 671 # The buildbot already builds and syncs to a specific revision. Don't fight
747 # with it or replicate work. 672 # with it or replicate work.
748 if sync_and_build() == 1: 673 if sync_and_build() == 1:
749 return # The build is broken. 674 return # The build is broken.
750 if size: 675 if size:
751 CompileTimeAndSizeTest(TIME_SIZE).run() 676 CompileTimeAndSizeTest(TIME_SIZE).run()
752 if cl: 677 if cl:
753 CommandLinePerformanceTest(CL_PERF).run() 678 CommandLinePerformanceTest(CL_PERF).run()
754 if language:
755 BrowserCorrectnessTest('language', BROWSER_CORRECTNESS).run()
756 if perf: 679 if perf:
757 BrowserPerformanceTest(BROWSER_PERF).run() 680 BrowserPerformanceTest(BROWSER_PERF).run()
758 681
759 if username != '': 682 if username != '':
760 upload_to_app_engine(username, password) 683 upload_to_app_engine(username, password)
761 684
762 def main(): 685 def main():
763 global VERBOSE 686 global VERBOSE
764 (cl, size, language, perf, continuous, verbose, username, password) = parse_ar gs() 687 (cl, size, perf, continuous, verbose, username, password) = parse_args()
765 VERBOSE = verbose 688 VERBOSE = verbose
766 if continuous: 689 if continuous:
767 while True: 690 while True:
768 if has_new_code(): 691 if has_new_code():
769 run_test_sequence(cl, size, language, perf, username, password) 692 run_test_sequence(cl, size, perf, username, password)
770 else: 693 else:
771 time.sleep(SLEEP_TIME) 694 time.sleep(SLEEP_TIME)
772 else: 695 else:
773 run_test_sequence(cl, size, language, perf, username, password) 696 run_test_sequence(cl, size, perf, username, password)
774 697
775 if __name__ == '__main__': 698 if __name__ == '__main__':
776 main() 699 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