| Index: tools/testing/perf_testing/create_graph.py
|
| ===================================================================
|
| --- tools/testing/perf_testing/create_graph.py (revision 5595)
|
| +++ tools/testing/perf_testing/create_graph.py (working copy)
|
| @@ -1,765 +0,0 @@
|
| -#!/usr/bin/python
|
| -
|
| -# Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
| -# for details. All rights reserved. Use of this source code is governed by a
|
| -# BSD-style license that can be found in the LICENSE file.
|
| -
|
| -import datetime
|
| -import math
|
| -from matplotlib.font_manager import FontProperties
|
| -import matplotlib.pyplot as plt
|
| -import optparse
|
| -import os
|
| -from os.path import dirname, abspath
|
| -import platform
|
| -import shutil
|
| -import subprocess
|
| -import time
|
| -import traceback
|
| -import sys
|
| -
|
| -TOOLS_PATH = os.path.join(dirname(dirname(dirname(abspath(__file__)))))
|
| -sys.path.append(TOOLS_PATH)
|
| -import utils
|
| -
|
| -"""This script runs to track performance and correctness progress of
|
| -different svn revisions. It tests to see if there a newer version of the code on
|
| -the server, and will sync and run the performance tests if so."""
|
| -
|
| -DART_INSTALL_LOCATION = os.path.join(dirname(abspath(__file__)),
|
| - '..', '..', '..')
|
| -V8_MEAN = 'V8 Mean'
|
| -FROG_MEAN = 'frog Mean'
|
| -COMMAND_LINE = 'commandline'
|
| -V8 = 'v8'
|
| -FROG = 'frog'
|
| -V8_AND_FROG = [V8, FROG]
|
| -CORRECTNESS = 'Percent passing'
|
| -COLORS = ['blue', 'green', 'red', 'cyan', 'magenta', 'black']
|
| -GRAPH_OUT_DIR = 'graphs'
|
| -
|
| -BROWSER_PERF = 'browser-perf'
|
| -TIME_SIZE = 'code-time-size'
|
| -CL_PERF = 'cl-results'
|
| -BROWSER_CORRECTNESS = 'browser-correctness'
|
| -
|
| -SLEEP_TIME = 200
|
| -VERBOSE = False
|
| -HAS_SHELL = False
|
| -if platform.system() == 'Windows':
|
| - # On Windows, shell must be true to get the correct environment variables.
|
| - HAS_SHELL = True
|
| -
|
| -"""First, some utility methods."""
|
| -
|
| -def run_cmd(cmd_list, outfile=None, append=False):
|
| - """Run the specified command and print out any output to stdout.
|
| -
|
| - Args:
|
| - cmd_list: a list of strings that make up the command to run
|
| - outfile: a string indicating the name of the file that we should write
|
| - stdout to
|
| - append: True if we want to append to the file instead of overwriting it"""
|
| - if VERBOSE:
|
| - print ' '.join(cmd_list)
|
| - out = subprocess.PIPE
|
| - if outfile:
|
| - mode = 'w'
|
| - if append:
|
| - mode = 'a'
|
| - out = open(outfile, mode)
|
| - if append:
|
| - # Annoying Windows "feature" -- append doesn't actually append unless you
|
| - # explicitly go to the end of the file.
|
| - # http://mail.python.org/pipermail/python-list/2009-October/1221859.html
|
| - out.seek(0, os.SEEK_END)
|
| - p = subprocess.Popen(cmd_list, stdout = out, stderr = subprocess.PIPE,
|
| - shell=HAS_SHELL)
|
| - output, not_used = p.communicate();
|
| - if output:
|
| - print output
|
| - return output
|
| -
|
| -def time_cmd(cmd):
|
| - """Determine the amount of (real) time it takes to execute a given command."""
|
| - start = time.time()
|
| - run_cmd(cmd)
|
| - return time.time() - start
|
| -
|
| -def sync_and_build():
|
| - """Make sure we have the latest version of of the repo, and build it. We
|
| - begin and end standing in DART_INSTALL_LOCATION.
|
| -
|
| - Returns:
|
| - err_code = 1 if there was a problem building."""
|
| - os.chdir(DART_INSTALL_LOCATION)
|
| - #Revert our newly built minfrog to prevent conflicts when we update
|
| - run_cmd(['svn', 'revert', os.path.join(os.getcwd(), 'frog', 'minfrog')])
|
| -
|
| - run_cmd(['gclient', 'sync'])
|
| -
|
| - # On Windows, the output directory is marked as "Read Only," which causes an
|
| - # error to be thrown when we use shutil.rmtree. This helper function changes
|
| - # the permissions so we can still delete the directory.
|
| - def on_rm_error(func, path, exc_info):
|
| - os.chmod(path, stat.S_IWRITE)
|
| - os.unlink(path)
|
| - # TODO(efortuna): building the sdk locally is a band-aid until all build
|
| - # platform SDKs are hosted in Google storage. Pull from https://sandbox.
|
| - # google.com/storage/?arg=dart-dump-render-tree#dart-dump-render-tree%2Fsdk
|
| - # eventually.
|
| - # TODO(efortuna): Currently always building ia32 architecture because we don't
|
| - # have test statistics for what's passing on x64. Eliminate arch specification
|
| - # when we have tests running on x64, too.
|
| - shutil.rmtree(os.path.join(os.getcwd(),
|
| - utils.GetBuildRoot(utils.GuessOS(), 'release', 'ia32')),
|
| - onerror=on_rm_error)
|
| - lines = run_cmd([os.path.join('.', 'tools', 'build.py'), '-m', 'release',
|
| - '--arch=ia32', 'create_sdk'])
|
| -
|
| - for line in lines:
|
| - if 'BUILD FAILED' in lines:
|
| - # Someone checked in a broken build! Just stop trying to make it work
|
| - # and wait to try again.
|
| - print 'Broken Build'
|
| - return 1
|
| - return 0
|
| -
|
| -def ensure_output_directory(dir_name):
|
| - """Test that the listed directory name exists, and if not, create one for
|
| - our output to be placed.
|
| -
|
| - Args:
|
| - dir_name: the directory we will create if it does not exist."""
|
| - dir_path = os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing',
|
| - 'perf_testing', dir_name)
|
| - if not os.path.exists(dir_path):
|
| - os.mkdir(dir_path)
|
| - print 'Creating output directory ', dir_path
|
| -
|
| -def has_new_code():
|
| - """Tests if there are any newer versions of files on the server."""
|
| - os.chdir(DART_INSTALL_LOCATION)
|
| - results = run_cmd(['svn', 'st', '-u'])
|
| - for line in results:
|
| - if '*' in line:
|
| - return True
|
| - return False
|
| -
|
| -def get_browsers():
|
| - browsers = ['ff', 'chrome']
|
| - if platform.system() == 'Darwin':
|
| - browsers += ['safari']
|
| - if platform.system() == 'Windows':
|
| - browsers += ['ie']
|
| - return browsers
|
| -
|
| -def get_versions():
|
| - return V8_AND_FROG
|
| -
|
| -def get_benchmarks():
|
| - return ['Mandelbrot', 'DeltaBlue', 'Richards', 'NBody', 'BinaryTrees',
|
| - 'Fannkuch', 'Meteor', 'BubbleSort', 'Fibonacci', 'Loop', 'Permute',
|
| - 'Queens', 'QuickSort', 'Recurse', 'Sieve', 'Sum', 'Tak', 'Takl', 'Towers',
|
| - 'TreeSort']
|
| -
|
| -def get_os_directory():
|
| - """Specifies the name of the directory for the testing build of dart, which
|
| - has yet a different naming convention from utils.getBuildRoot(...)."""
|
| - if platform.system() == 'Windows':
|
| - return 'windows'
|
| - elif platform.system() == 'Darwin':
|
| - return 'macos'
|
| - else:
|
| - return 'linux'
|
| -
|
| -def upload_to_app_engine():
|
| - """Upload our results to our appengine server."""
|
| - # TODO(efortuna): This is the most basic way to get the data up
|
| - # for others to view. Revisit this once we're serving nicer graphs (Google
|
| - # Chart Tools) and from multiple perfbots and once we're in a position to
|
| - # organize the data in a useful manner(!!).
|
| - os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', 'testing',
|
| - 'perf_testing'))
|
| - shutil.rmtree(os.path.join('appengine', 'static', 'graphs'),
|
| - ignore_errors=True)
|
| - shutil.copytree('graphs', os.path.join('appengine', 'static', 'graphs'))
|
| - shutil.copyfile('index.html', os.path.join('appengine', 'static',
|
| - 'index.html'))
|
| - run_cmd(['../../../third_party/appengine-python/1.5.4/appcfg.py', 'update',
|
| - 'appengine/'])
|
| -
|
| -class TestRunner(object):
|
| - """The base clas to provide shared code for different tests we will run and
|
| - graph."""
|
| -
|
| - def __init__(self, result_folder_name, platform_list, v8_and_or_frog_list,
|
| - values_list):
|
| - """Args:
|
| - result_folder_name the name of the folder where a tracefile of
|
| - performance results will be stored.
|
| - platform_list a list containing the platform(s) that our data has been
|
| - run on. (command line, firefox, chrome, etc)
|
| - v8_and_or_frog_list a list specifying whether we hold data about Frog
|
| - generated code, plain JS code (v8), or a combination of both.
|
| - values_list a list containing the type of data we will be graphing
|
| - (benchmarks, percentage passing, etc)"""
|
| - self.result_folder_name = result_folder_name
|
| - # cur_time is used as a timestamp of when this performance test was run.
|
| - self.cur_time = str(time.mktime(datetime.datetime.now().timetuple()))
|
| - self.browser_color = {'chrome': 'green', 'ie': 'blue', 'ff': 'red',
|
| - 'safari':'black'}
|
| - self.values_list = values_list
|
| - self.platform_list = platform_list
|
| - self.revision_dict = dict()
|
| - self.values_dict = dict()
|
| - self.color_index = 0
|
| - for platform in platform_list:
|
| - self.revision_dict[platform] = dict()
|
| - self.values_dict[platform] = dict()
|
| - for f in v8_and_or_frog_list:
|
| - self.revision_dict[platform][f] = dict()
|
| - self.values_dict[platform][f] = dict()
|
| - for val in values_list:
|
| - self.revision_dict[platform][f][val] = []
|
| - self.values_dict[platform][f][val] = []
|
| - if V8 in v8_and_or_frog_list:
|
| - self.revision_dict[platform][V8][V8_MEAN] = []
|
| - self.values_dict[platform][V8][V8_MEAN] = []
|
| - if FROG in v8_and_or_frog_list:
|
| - self.revision_dict[platform][FROG][FROG_MEAN] = []
|
| - self.values_dict[platform][FROG][FROG_MEAN] = []
|
| -
|
| - def get_color(self):
|
| - color = COLORS[self.color_index]
|
| - self.color_index = (self.color_index + 1) % len(COLORS)
|
| - return color
|
| -
|
| - def style_and_save_perf_plot(self, chart_title, y_axis_label, size_x, size_y,
|
| - legend_loc, filename, platform_list, v8_and_or_frog_list, values_list,
|
| - should_clear_axes=True):
|
| - """Sets style preferences for chart boilerplate that is consistent across
|
| - all charts, and saves the chart as a png.
|
| -
|
| - Args:
|
| - size_x: the size of the printed chart, in inches, in the horizontal
|
| - direction
|
| - size_y: the size of the printed chart, in inches in the vertical direction
|
| - legend_loc: the location of the legend in on the chart. See suitable
|
| - arguments for the loc argument in matplotlib
|
| - filename: the filename that we want to save the resulting chart as
|
| - platform_list: a list containing the platform(s) that our data has been
|
| - run on. (command line, firefox, chrome, etc)
|
| - values_list: a list containing the type of data we will be graphing
|
| - (performance, percentage passing, etc)
|
| - should_clear_axes: True if we want to create a fresh graph, instead of
|
| - plotting additional lines on the current graph."""
|
| - if should_clear_axes:
|
| - plt.cla() # cla = clear current axes
|
| - for platform in platform_list:
|
| - for f in v8_and_or_frog_list:
|
| - for val in values_list:
|
| - plt.plot(self.revision_dict[platform][f][val],
|
| - self.values_dict[platform][f][val],
|
| - color=self.get_color(), label='%s-%s-%s' % (platform, f, val))
|
| -
|
| - plt.xlabel('Revision Number')
|
| - plt.ylabel(y_axis_label)
|
| - plt.title(chart_title)
|
| - fontP = FontProperties()
|
| - fontP.set_size('small')
|
| - plt.legend(loc=legend_loc, prop = fontP)
|
| -
|
| - fig = plt.gcf()
|
| - fig.set_size_inches(size_x, size_y)
|
| - fig.savefig(os.path.join(GRAPH_OUT_DIR, filename))
|
| -
|
| - def add_svn_revision_to_trace(self, outfile):
|
| - """Add the svn version number to the provided tracefile."""
|
| - def search_for_revision(svn_info_command):
|
| - p = subprocess.Popen(svn_info_command, stdout = subprocess.PIPE,
|
| - stderr = subprocess.STDOUT, shell = HAS_SHELL)
|
| - output, _ = p.communicate()
|
| - for line in output.split('\n'):
|
| - if 'Revision' in line:
|
| - run_cmd(['echo', line.strip()], outfile)
|
| - return True
|
| - return False
|
| -
|
| - if not search_for_revision(['svn', 'info']):
|
| - if not search_for_revision(['git', 'svn', 'info']):
|
| - run_cmd(['echo', 'Revision: unknown'], outfile)
|
| -
|
| - def write_html(self, delimiter, rev_nums, label_1, dict_1, label_2, dict_2,
|
| - cleanFile=False):
|
| - """Adds an html table to the webpage to display the data values. This method
|
| - will be removed when we have a nicer way to display data values."""
|
| - #TODO(efortuna): fix this.
|
| - return
|
| - #TODO(efortuna): Take this method out when have finalized where the data is
|
| - # going to be displayed.
|
| - f = ''
|
| - out = ''
|
| - if cleanFile:
|
| - f = open('template.html')
|
| - else:
|
| - shutil.copy('index.html', 'temp.html')
|
| - f = open('temp.html')
|
| - out = open('index.html', 'w')
|
| - inTable = False
|
| - for line in f.readlines():
|
| - if not inTable:
|
| - out.write(line)
|
| - if delimiter in line:
|
| - inTable = not inTable
|
| - if inTable:
|
| - out.write('<table border="1"> <tr> <td> svn revision </td>')
|
| - for revision in rev_nums:
|
| - out.write('<td>%d</td>' % revision)
|
| - out.write('</tr>\n<tr><td> %s</td>' % label_1)
|
| - for perf in dict_1:
|
| - out.write('<td>%f</td>' % perf)
|
| - out.write('</tr>\n<tr><td> %s</td>' % label_2)
|
| - for perf in dict_2:
|
| - out.write('<td>%f</td>' % perf)
|
| - out.write('</tr> </table>')
|
| -
|
| - def calculate_geometric_mean(self, platform, frog_or_v8, svn_revision):
|
| - """Calculate the aggregate geometric mean for V8 and frog benchmark sets,
|
| - given two benchmark dictionaries."""
|
| - geo_mean = 0
|
| - for benchmark in get_benchmarks():
|
| - geo_mean += math.log(self.values_dict[platform][frog_or_v8][benchmark][
|
| - len(self.values_dict[platform][frog_or_v8][benchmark]) - 1])
|
| -
|
| - mean = V8_MEAN
|
| - if frog_or_v8 == FROG:
|
| - mean = FROG_MEAN
|
| - self.values_dict[platform][frog_or_v8][mean] += \
|
| - [math.pow(math.e, geo_mean / len(get_benchmarks()))]
|
| - self.revision_dict[platform][frog_or_v8][mean] += [svn_revision]
|
| -
|
| - def run(self):
|
| - """Run the benchmarks/tests from the command line and plot the
|
| - results."""
|
| - plt.cla() # cla = clear current axes
|
| - os.chdir(DART_INSTALL_LOCATION)
|
| - ensure_output_directory(self.result_folder_name)
|
| - ensure_output_directory(GRAPH_OUT_DIR)
|
| - self.run_tests()
|
| - os.chdir(os.path.join('tools', 'testing', 'perf_testing'))
|
| -
|
| - # TODO(efortuna): You will want to make this only use a subset of the files
|
| - # eventually.
|
| - files = os.listdir(self.result_folder_name)
|
| -
|
| - for afile in files:
|
| - if not afile.startswith('.'):
|
| - self.process_file(afile)
|
| -
|
| - self.plot_results('%s.png' % self.result_folder_name)
|
| -
|
| -class PerformanceTest(TestRunner):
|
| - """Super class for all performance testing."""
|
| - def __init__(self, result_folder_name, platform_list, platform_type):
|
| - super(PerformanceTest, self).__init__(result_folder_name,
|
| - platform_list, get_versions(), get_benchmarks())
|
| - self.platform_list = platform_list
|
| - self.platform_type = platform_type
|
| -
|
| - def plot_all_perf(self, png_filename):
|
| - """Create a plot that shows the performance changes of individual benchmarks
|
| - run by V8 and generated by frog, over svn history."""
|
| - for benchmark in get_benchmarks():
|
| - self.style_and_save_perf_plot(
|
| - 'Performance of %s over time on the %s' % (benchmark,
|
| - self.platform_type), 'Speed (bigger = better)', 16, 14, 'lower left',
|
| - benchmark + png_filename, self.platform_list, get_versions(),
|
| - [benchmark])
|
| -
|
| - def plot_avg_perf(self, png_filename):
|
| - """Generate a plot that shows the performance changes of the geomentric mean
|
| - of V8 and frog benchmark performance over svn history."""
|
| - (title, y_axis, size_x, size_y, loc, filename) = \
|
| - ('Geometric Mean of benchmark %s performance' % self.platform_type,
|
| - 'Speed (bigger = better)', 16, 5, 'center', 'avg'+png_filename)
|
| - clear_axis = True
|
| - for platform in self.platform_list:
|
| - self.style_and_save_perf_plot(title, y_axis, size_x, size_y, loc,
|
| - filename, [platform], [V8], [V8_MEAN], clear_axis)
|
| - clear_axis = False
|
| - self.style_and_save_perf_plot(title, y_axis, size_x, size_y, loc,
|
| - filename, [platform], [FROG], [FROG_MEAN], clear_axis)
|
| -
|
| - def plot_results(self, png_filename):
|
| - self.plot_all_perf(png_filename)
|
| - self.plot_avg_perf('2' + png_filename)
|
| -
|
| -
|
| -class CommandLinePerformanceTest(PerformanceTest):
|
| - """Run performance tests from the command line."""
|
| -
|
| - def __init__(self, result_folder_name):
|
| - super(CommandLinePerformanceTest, self).__init__(result_folder_name,
|
| - [COMMAND_LINE], 'command line')
|
| -
|
| - def process_file(self, afile):
|
| - """Pull all the relevant information out of a given tracefile.
|
| -
|
| - Args:
|
| - afile: The filename string we will be processing."""
|
| - f = open(os.path.join(self.result_folder_name, afile))
|
| - tabulate_data = False
|
| - revision_num = 0
|
| - for line in f.readlines():
|
| - if 'Revision' in line:
|
| - revision_num = int(line.split()[1])
|
| - elif 'Benchmark' in line:
|
| - tabulate_data = True
|
| - elif tabulate_data:
|
| - tokens = line.split()
|
| - if len(tokens) < 4 or tokens[0] not in get_benchmarks():
|
| - #Done tabulating data.
|
| - break
|
| - v8_value = float(tokens[1])
|
| - frog_value = float(tokens[3])
|
| - if v8_value == 0 or frog_value == 0:
|
| - #Then there was an error when this performance test was run. Do not
|
| - #count it in our numbers.
|
| - return
|
| - benchmark = tokens[0]
|
| - self.revision_dict[COMMAND_LINE][V8][benchmark] += [revision_num]
|
| - self.values_dict[COMMAND_LINE][V8][benchmark] += [v8_value]
|
| - self.revision_dict[COMMAND_LINE][FROG][benchmark] += [revision_num]
|
| - self.values_dict[COMMAND_LINE][FROG][benchmark] += [frog_value]
|
| - f.close()
|
| -
|
| - self.calculate_geometric_mean(COMMAND_LINE, FROG, revision_num)
|
| - self.calculate_geometric_mean(COMMAND_LINE, V8, revision_num)
|
| -
|
| - def run_tests(self):
|
| - """Run a performance test on our updated system."""
|
| - os.chdir('frog')
|
| - self.trace_file = os.path.join('..', 'tools', 'testing', 'perf_testing',
|
| - self.result_folder_name, 'result' + self.cur_time)
|
| - run_cmd(['python', os.path.join('benchmarks', 'perf_tests.py')],
|
| - self.trace_file)
|
| - os.chdir('..')
|
| -
|
| -
|
| -class BrowserPerformanceTest(PerformanceTest):
|
| - """Runs performance tests, in the browser."""
|
| -
|
| - def __init__(self, result_folder_name):
|
| - super(BrowserPerformanceTest, self).__init__(
|
| - result_folder_name, get_browsers(), 'browser')
|
| -
|
| - def run_tests(self):
|
| - """Run a performance test in the browser."""
|
| -
|
| - os.chdir('frog')
|
| - run_cmd(['python', os.path.join('benchmarks', 'make_web_benchmarks.py')])
|
| - os.chdir('..')
|
| -
|
| - for browser in get_browsers():
|
| - for version in get_versions():
|
| - self.trace_file = os.path.join('tools', 'testing', 'perf_testing',
|
| - self.result_folder_name,
|
| - 'perf-%s-%s-%s' % (self.cur_time, browser, version))
|
| - self.add_svn_revision_to_trace(self.trace_file)
|
| - file_path = os.path.join(os.getcwd(), 'internal', 'browserBenchmarks',
|
| - 'benchmark_page_%s.html' % version)
|
| - run_cmd(['python', os.path.join('tools', 'testing', 'run_selenium.py'),
|
| - '--out', file_path, '--browser', browser,
|
| - '--timeout', '600', '--perf'], self.trace_file, append=True)
|
| -
|
| - def process_file(self, afile):
|
| - """Comb through the html to find the performance results."""
|
| - parts = afile.split('-')
|
| - browser = parts[2]
|
| - version = parts[3]
|
| - f = open(os.path.join(self.result_folder_name, afile))
|
| - lines = f.readlines()
|
| - line = ''
|
| - i = 0
|
| - revision_num = 0
|
| - while '<div id="results">' not in line and i < len(lines):
|
| - if 'Revision' in line:
|
| - revision_num = int(line.split()[1])
|
| - line = lines[i]
|
| - i += 1
|
| -
|
| - if i >= len(lines) or revision_num == 0:
|
| - # Then this run did not complete. Ignore this tracefile.
|
| - return
|
| -
|
| - line = lines[i]
|
| - i += 1
|
| - results = []
|
| - if line.find('<br>') > -1:
|
| - results = line.split('<br>')
|
| - else:
|
| - results = line.split('<br />')
|
| - for result in results:
|
| - name_and_score = result.split(':')
|
| - if len(name_and_score) < 2:
|
| - break
|
| - name = name_and_score[0].strip()
|
| - score = name_and_score[1].strip()
|
| - if version == V8:
|
| - bench_dict = self.values_dict[browser][V8]
|
| - else:
|
| - bench_dict = self.values_dict[browser][FROG]
|
| - bench_dict[name] += [float(score)]
|
| - self.revision_dict[browser][version][name] += [revision_num]
|
| -
|
| - f.close()
|
| - self.calculate_geometric_mean(browser, version, revision_num)
|
| -
|
| - def write_html(self, delimiter, rev_nums, label_1, dict_1, label_2, dict_2,
|
| - cleanFile=False):
|
| - #TODO(efortuna)
|
| - pass
|
| -
|
| -
|
| -class BrowserCorrectnessTest(TestRunner):
|
| - def __init__(self, test_type, result_folder_name):
|
| - super(BrowserCorrectnessTest, self).__init__(result_folder_name,
|
| - get_browsers(), [FROG], [CORRECTNESS])
|
| - self.test_type = test_type
|
| -
|
| - def run_tests(self):
|
| - """Run a test of the latest svn revision."""
|
| - system = get_os_directory()
|
| - suffix = ''
|
| - if platform.system() == 'Windows':
|
| - suffix = '.exe'
|
| - for browser in get_browsers():
|
| - current_file = 'correctness%s-%s' % (self.cur_time, browser)
|
| - self.trace_file = os.path.join('tools', 'testing',
|
| - 'perf_testing', self.result_folder_name, current_file)
|
| - self.add_svn_revision_to_trace(self.trace_file)
|
| - dart_sdk = os.path.join(os.getcwd(), utils.GetBuildRoot(utils.GuessOS(),
|
| - 'release', 'ia32'), 'dart-sdk')
|
| - run_cmd([os.path.join('.', 'tools', 'testing', 'bin', system,
|
| - 'dart' + suffix), os.path.join('tools', 'test.dart'),
|
| - '--component=webdriver',
|
| - '--browser=%s' % browser, '--frog=%s' % os.path.join(dart_sdk, 'bin',
|
| - 'frogc'), '--froglib=%s' % os.path.join(dart_sdk, 'lib'), '--report',
|
| - '--timeout=20', '--progress=color', '--mode=release', '-j1',
|
| - self.test_type], self.trace_file, append=True)
|
| -
|
| - def process_file(self, afile):
|
| - """Given a trace file, extract all the relevant information out of it to
|
| - determine the number of correctly passing tests.
|
| -
|
| - Arguments:
|
| - afile: the filename string"""
|
| - browser = afile.rpartition('-')[2]
|
| - f = open(os.path.join(self.result_folder_name, afile))
|
| - revision_num = 0
|
| - lines = f.readlines()
|
| - total_tests = 0
|
| - num_failed = 0
|
| - expect_fail = 0
|
| - for line in lines:
|
| - if 'Total:' in line:
|
| - total_tests = int(line.split('Total: ')[1].split()[0])
|
| - if 'will be skipped' in line:
|
| - total_tests -= int(line.split()[1])
|
| - if 'we should fix' in line:
|
| - expect_fail += int(line.split()[1])
|
| - if 'Revision' in line:
|
| - revision_num = int(line.split()[1])
|
| - if '--- TIMEOUT ---' in line or 'FAIL:' in line or 'PASS' in line:
|
| - # (A printed out 'PASS' indicates we incorrectly passed a negative
|
| - # test.)
|
| - num_failed += 1
|
| -
|
| - self.revision_dict[browser][FROG][CORRECTNESS] += [revision_num]
|
| - self.values_dict[browser][FROG][CORRECTNESS] += [100.0 *
|
| - (((float)(total_tests - (expect_fail + num_failed))) /total_tests)]
|
| - f.close()
|
| -
|
| - def plot_results(self, png_filename):
|
| - first_time = True
|
| - for browser in get_browsers():
|
| - self.style_and_save_perf_plot('Percentage of language tests passing in '
|
| - 'different browsers', '% of tests passed', 8, 8, 'lower left',
|
| - png_filename, [browser], [FROG], [CORRECTNESS], first_time)
|
| - first_time = False
|
| -
|
| -
|
| -class CompileTimeAndSizeTest(TestRunner):
|
| - """Run tests to determine how long minfrog takes to compile, and the compiled
|
| - file output size of some benchmarking files."""
|
| - def __init__(self, result_folder_name):
|
| - super(CompileTimeAndSizeTest, self).__init__(result_folder_name,
|
| - [COMMAND_LINE], [FROG], ['Compiling on Dart VM', 'Bootstrapping',
|
| - 'minfrog', 'swarm', 'total'])
|
| - self.failure_threshold = {'Compiling on Dart VM' : 1, 'Bootstrapping' : .5,
|
| - 'minfrog' : 100, 'swarm' : 100, 'total' : 100}
|
| -
|
| - def run_tests(self):
|
| - os.chdir('frog')
|
| - self.trace_file = os.path.join('..', 'tools', 'testing', 'perf_testing',
|
| - self.result_folder_name, self.result_folder_name + self.cur_time)
|
| -
|
| - self.add_svn_revision_to_trace(self.trace_file)
|
| -
|
| - suffix = ''
|
| - if platform.system() == 'Windows':
|
| - suffix = '.exe'
|
| - elapsed = time_cmd([os.path.join('..', utils.GetBuildRoot(utils.GuessOS(),
|
| - 'release', 'ia32'), 'dart' + suffix), os.path.join('.', 'minfrogc.dart'),
|
| - '--out=minfrog', 'minfrog.dart'])
|
| - run_cmd(['echo', '%f Compiling on Dart VM in production mode in seconds'
|
| - % elapsed], self.trace_file, append=True)
|
| - elapsed = time_cmd([os.path.join('.', 'minfrog'), '--out=minfrog',
|
| - 'minfrog.dart', os.path.join('tests', 'hello.dart')])
|
| - if elapsed < self.failure_threshold['Bootstrapping']:
|
| - #minfrog didn't compile correctly. Stop testing now, because subsequent
|
| - #numbers will be meaningless.
|
| - return
|
| - size = os.path.getsize('minfrog')
|
| - run_cmd(['echo', '%f Bootstrapping time in seconds in production mode' %
|
| - elapsed], self.trace_file, append=True)
|
| - run_cmd(['echo', '%d Generated checked minfrog size' % size],
|
| - self.trace_file, append=True)
|
| -
|
| - run_cmd([os.path.join('.', 'minfrog'), '--out=swarm-result',
|
| - '--compile-only', os.path.join('..', 'samples', 'swarm',
|
| - 'swarm.dart')])
|
| - swarm_size = 0
|
| - try:
|
| - swarm_size = os.path.getsize('swarm-result')
|
| - except OSError:
|
| - pass #If compilation failed, continue on running other tests.
|
| -
|
| - run_cmd([os.path.join('.', 'minfrog'), '--out=total-result',
|
| - '--compile-only', os.path.join('..', 'samples', 'total',
|
| - 'client', 'Total.dart')])
|
| - total_size = 0
|
| - try:
|
| - total_size = os.path.getsize('total-result')
|
| - except OSError:
|
| - pass #If compilation failed, continue on running other tests.
|
| -
|
| - run_cmd(['echo', '%d Generated checked swarm size' % swarm_size],
|
| - self.trace_file, append=True)
|
| -
|
| - run_cmd(['echo', '%d Generated checked total size' % total_size],
|
| - self.trace_file, append=True)
|
| - os.chdir('..')
|
| -
|
| - def process_file(self, afile):
|
| - """Pull all the relevant information out of a given tracefile.
|
| -
|
| - Args:
|
| - afile: is the filename string we will be processing."""
|
| - f = open(os.path.join(self.result_folder_name, afile))
|
| - tabulate_data = False
|
| - revision_num = 0
|
| - for line in f.readlines():
|
| - tokens = line.split()
|
| - if 'Revision' in line:
|
| - revision_num = int(line.split()[1])
|
| - else:
|
| - for metric in self.values_list:
|
| - if metric in line:
|
| - num = tokens[0]
|
| - if num.find('.') == -1:
|
| - num = int(num)
|
| - else:
|
| - num = float(num)
|
| - self.values_dict[COMMAND_LINE][FROG][metric] += [num]
|
| - self.revision_dict[COMMAND_LINE][FROG][metric] += [revision_num]
|
| -
|
| - if revision_num != 0:
|
| - for metric in self.values_list:
|
| - self.revision_dict[COMMAND_LINE][FROG][metric].pop()
|
| - self.revision_dict[COMMAND_LINE][FROG][metric] += [revision_num]
|
| - # Fill in 0 if compilation failed.
|
| - if self.values_dict[COMMAND_LINE][FROG][metric][-1] < \
|
| - self.failure_threshold[metric]:
|
| - self.values_dict[COMMAND_LINE][FROG][metric] += [0]
|
| - self.revision_dict[COMMAND_LINE][FROG][metric] += [revision_num]
|
| -
|
| - f.close()
|
| -
|
| - def plot_results(self, png_filename):
|
| - self.style_and_save_perf_plot('Compiled minfrog Sizes',
|
| - 'Size (in bytes)', 10, 10, 'center', png_filename, [COMMAND_LINE],
|
| - [FROG], ['swarm', 'total', 'minfrog'])
|
| - self.write_html('bar', self.revision_dict[COMMAND_LINE][FROG]['minfrog'],
|
| - 'minfrog size', self.values_dict[COMMAND_LINE][FROG]['minfrog'], '', [])
|
| -
|
| - self.style_and_save_perf_plot('Time to compile and bootstrap',
|
| - 'Seconds', 10, 10, 'center', '2' + png_filename, [COMMAND_LINE], [FROG],
|
| - ['Bootstrapping', 'Compiling on Dart VM'])
|
| - self.write_html('baz',
|
| - self.revision_dict[COMMAND_LINE][FROG]['Bootstrapping'],
|
| - 'Bootstrapping', self.values_dict[COMMAND_LINE][FROG]['Bootstrapping'],
|
| - 'Compiling on Dart VM',
|
| - self.values_dict[COMMAND_LINE][FROG]['Compiling on Dart VM'])
|
| -
|
| -
|
| -def parse_args():
|
| - parser = optparse.OptionParser()
|
| - parser.add_option('--command-line', '-c', dest='cl',
|
| - help = 'Run the command line tests',
|
| - action = 'store_true', default = False)
|
| - parser.add_option('--size-time', '-s', dest = 'size',
|
| - help = 'Run the code size and timing tests',
|
| - action = 'store_true', default = False)
|
| - parser.add_option('--language', '-l', dest = 'language',
|
| - help = 'Run the language correctness tests',
|
| - action = 'store_true', default = False)
|
| - parser.add_option('--browser-perf', '-b', dest = 'perf',
|
| - help = 'Run the browser performance tests',
|
| - action = 'store_true', default = False)
|
| - parser.add_option('--forever', '-f', dest = 'continuous',
|
| - help = 'Run this script forever, always checking for the next svn '
|
| - 'checkin', action = 'store_true', default = False)
|
| - parser.add_option('--verbose', '-v', dest = 'verbose',
|
| - help = 'Print extra debug output', action = 'store_true', default = False)
|
| -
|
| - args, ignored = parser.parse_args()
|
| - if not (args.cl or args.size or args.language or args.perf):
|
| - args.cl = args.size = args.language = args.perf = True
|
| - return (args.cl, args.size, args.language, args.perf, args.continuous,
|
| - args.verbose)
|
| -
|
| -def run_test_sequence(cl, size, language, perf):
|
| - # The buildbot already builds and syncs to a specific revision. Don't fight
|
| - # with it or replicate work.
|
| - if sync_and_build() == 1:
|
| - return # The build is broken.
|
| - if size:
|
| - CompileTimeAndSizeTest(TIME_SIZE).run()
|
| - if cl:
|
| - CommandLinePerformanceTest(CL_PERF).run()
|
| - if language:
|
| - BrowserCorrectnessTest('language', BROWSER_CORRECTNESS).run()
|
| - if perf:
|
| - BrowserPerformanceTest(BROWSER_PERF).run()
|
| -
|
| - # TODO(efortuna): Temporarily disabled until you make a safe way to provide
|
| - # your username/password for the uploading process.
|
| - #upload_to_app_engine()
|
| -
|
| -def main():
|
| - global VERBOSE
|
| - (cl, size, language, perf, continuous, verbose) = parse_args()
|
| - VERBOSE = verbose
|
| - if continuous:
|
| - while True:
|
| - if has_new_code():
|
| - run_test_sequence(cl, size, language, perf)
|
| - else:
|
| - time.sleep(SLEEP_TIME)
|
| - else:
|
| - run_test_sequence(cl, size, language, perf)
|
| -
|
| -if __name__ == '__main__':
|
| - main()
|
|
|