| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 3 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 4 # for details. All rights reserved. Use of this source code is governed by a | 4 # for details. All rights reserved. Use of this source code is governed by a |
| 5 # BSD-style license that can be found in the LICENSE file. | 5 # BSD-style license that can be found in the LICENSE file. |
| 6 | 6 |
| 7 import datetime | 7 import datetime |
| 8 import math | 8 import math |
| 9 import optparse | 9 import optparse |
| 10 import os | 10 import os |
| 11 from os.path import dirname, abspath | 11 from os.path import dirname, abspath |
| 12 import pickle | 12 import pickle |
| 13 import platform | 13 import platform |
| 14 import random | 14 import random |
| 15 import re | 15 import re |
| 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 | 21 |
| 22 TOOLS_PATH = os.path.join(dirname(dirname(dirname(abspath(__file__))))) | 22 TOOLS_PATH = os.path.join(dirname(dirname(dirname(abspath(__file__))))) |
| 23 TOP_LEVEL_DIR = abspath(os.path.join(dirname(abspath(__file__)), '..', '..', | 23 TOP_LEVEL_DIR = abspath(os.path.join(dirname(abspath(__file__)), '..', '..', |
| 24 '..')) | 24 '..')) |
| 25 DART_REPO_LOC = abspath(os.path.join(dirname(abspath(__file__)), '..', '..', | 25 DART_REPO_LOC = abspath(os.path.join(dirname(abspath(__file__)), '..', '..', |
| 26 '..', '..', '..', | 26 '..', '..', '..', |
| 27 'dart_checkout_for_perf_testing', | 27 'dart_checkout_for_perf_testing', |
| 28 'dart')) | 28 'dart')) |
| 29 # The earliest stored version of Dartium. Don't try to test earlier than this. | 29 # How far back in time we want to test. |
| 30 EARLIEST_REVISION = 4285 | 30 EARLIEST_REVISION = 6285 |
| 31 FIRST_CHROMEDRIVER = 7823 | 31 FIRST_CHROMEDRIVER = 7823 |
| 32 sys.path.append(TOOLS_PATH) | 32 sys.path.append(TOOLS_PATH) |
| 33 sys.path.append(os.path.join(TOP_LEVEL_DIR, 'internal', 'tests')) | 33 sys.path.append(os.path.join(TOP_LEVEL_DIR, 'internal', 'tests')) |
| 34 import post_results | 34 import post_results |
| 35 import utils | 35 import utils |
| 36 | 36 |
| 37 """This script runs to track performance and size progress of | 37 """This script runs to track performance and size progress of |
| 38 different svn revisions. It tests to see if there a newer version of the code on | 38 different svn revisions. It tests to see if there a newer version of the code on |
| 39 the server, and will sync and run the performance tests if so.""" | 39 the server, and will sync and run the performance tests if so.""" |
| 40 class TestRunner(object): | 40 class TestRunner(object): |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 p = subprocess.Popen(cmd_list, stdout = out, stderr=subprocess.PIPE, | 73 p = subprocess.Popen(cmd_list, stdout = out, stderr=subprocess.PIPE, |
| 74 stdin=subprocess.PIPE, shell=self.has_shell) | 74 stdin=subprocess.PIPE, shell=self.has_shell) |
| 75 output, stderr = p.communicate(std_in) | 75 output, stderr = p.communicate(std_in) |
| 76 if output: | 76 if output: |
| 77 print output | 77 print output |
| 78 if stderr: | 78 if stderr: |
| 79 print stderr | 79 print stderr |
| 80 return output, stderr | 80 return output, stderr |
| 81 | 81 |
| 82 def TimeCmd(self, cmd): | 82 def TimeCmd(self, cmd): |
| 83 """Determine the amount of (real) time it takes to execute a given | 83 """Determine the amount of (real) time it takes to execute a given |
| 84 command.""" | 84 command.""" |
| 85 start = time.time() | 85 start = time.time() |
| 86 self.RunCmd(cmd) | 86 self.RunCmd(cmd) |
| 87 return time.time() - start | 87 return time.time() - start |
| 88 | 88 |
| 89 def ClearOutUnversionedFiles(self): | 89 def ClearOutUnversionedFiles(self): |
| 90 """Remove all files that are unversioned by svn.""" | 90 """Remove all files that are unversioned by svn.""" |
| 91 if os.path.exists(DART_REPO_LOC): | 91 if os.path.exists(DART_REPO_LOC): |
| 92 os.chdir(DART_REPO_LOC) | 92 os.chdir(DART_REPO_LOC) |
| 93 results, _ = self.RunCmd(['svn', 'st']) | 93 results, _ = self.RunCmd(['svn', 'st']) |
| 94 for line in results.split('\n'): | 94 for line in results.split('\n'): |
| 95 if line.startswith('?'): | 95 if line.startswith('?'): |
| 96 to_remove = line.split()[1] | 96 to_remove = line.split()[1] |
| 97 if os.path.isdir(to_remove): | 97 if os.path.isdir(to_remove): |
| 98 shutil.rmtree(to_remove, ignore_errors=True) | 98 shutil.rmtree(to_remove, onerror=TestRunner._OnRmError) |
| 99 else: | 99 else: |
| 100 os.remove(to_remove) | 100 os.remove(to_remove) |
| 101 elif any(line.startswith(status) for status in ['A', 'M', 'C', 'D']): | 101 elif any(line.startswith(status) for status in ['A', 'M', 'C', 'D']): |
| 102 self.RunCmd(['svn', 'revert', line.split()[1]]) | 102 self.RunCmd(['svn', 'revert', line.split()[1]]) |
| 103 | 103 |
| 104 def GetArchive(self, archive_name): | 104 def GetArchive(self, archive_name): |
| 105 """Wrapper around the pulling down a specific archive from Google Storage. | 105 """Wrapper around the pulling down a specific archive from Google Storage. |
| 106 Adds a specific revision argument as needed. | 106 Adds a specific revision argument as needed. |
| 107 Returns: A tuple of a boolean (True if we successfully downloaded the | 107 Returns: A tuple of a boolean (True if we successfully downloaded the |
| 108 binary), and the stdout and stderr from running this command.""" | 108 binary), and the stdout and stderr from running this command.""" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 121 return (num_fails < 20, stdout, stderr) | 121 return (num_fails < 20, stdout, stderr) |
| 122 | 122 |
| 123 def _Sync(self, revision_num=None): | 123 def _Sync(self, revision_num=None): |
| 124 """Update the repository to the latest or specified revision.""" | 124 """Update the repository to the latest or specified revision.""" |
| 125 os.chdir(dirname(DART_REPO_LOC)) | 125 os.chdir(dirname(DART_REPO_LOC)) |
| 126 self.ClearOutUnversionedFiles() | 126 self.ClearOutUnversionedFiles() |
| 127 if not revision_num: | 127 if not revision_num: |
| 128 self.RunCmd(['gclient', 'sync']) | 128 self.RunCmd(['gclient', 'sync']) |
| 129 else: | 129 else: |
| 130 self.RunCmd(['gclient', 'sync', '-r', str(revision_num), '-t']) | 130 self.RunCmd(['gclient', 'sync', '-r', str(revision_num), '-t']) |
| 131 | 131 |
| 132 shutil.copytree(os.path.join(TOP_LEVEL_DIR, 'internal'), | 132 shutil.copytree(os.path.join(TOP_LEVEL_DIR, 'internal'), |
| 133 os.path.join(DART_REPO_LOC, 'internal')) | 133 os.path.join(DART_REPO_LOC, 'internal')) |
| 134 shutil.rmtree(os.path.join(DART_REPO_LOC, 'third_party', 'gsutil'), |
| 135 onerror=TestRunner._OnRmError) |
| 136 shutil.copytree(os.path.join(TOP_LEVEL_DIR, 'third_party', 'gsutil'), |
| 137 os.path.join(DART_REPO_LOC, 'third_party', 'gsutil')) |
| 134 shutil.copy(os.path.join(TOP_LEVEL_DIR, 'tools', 'get_archive.py'), | 138 shutil.copy(os.path.join(TOP_LEVEL_DIR, 'tools', 'get_archive.py'), |
| 135 os.path.join(DART_REPO_LOC, 'tools', 'get_archive.py')) | 139 os.path.join(DART_REPO_LOC, 'tools', 'get_archive.py')) |
| 136 shutil.copy( | 140 shutil.copy( |
| 137 os.path.join(TOP_LEVEL_DIR, 'tools', 'testing', 'run_selenium.py'), | 141 os.path.join(TOP_LEVEL_DIR, 'tools', 'testing', 'run_selenium.py'), |
| 138 os.path.join(DART_REPO_LOC, 'tools', 'testing', 'run_selenium.py')) | 142 os.path.join(DART_REPO_LOC, 'tools', 'testing', 'run_selenium.py')) |
| 139 | 143 |
| 144 @staticmethod |
| 145 def _OnRmError(func, path, exc_info): |
| 146 """On Windows, the output directory is marked as "Read Only," which causes |
| 147 an error to be thrown when we use shutil.rmtree. This helper function |
| 148 changes the permissions so we can still delete the directory.""" |
| 149 if os.path.exists(path): |
| 150 os.chmod(path, stat.S_IWRITE) |
| 151 os.unlink(path) |
| 152 |
| 140 def SyncAndBuild(self, suites, revision_num=None): | 153 def SyncAndBuild(self, suites, revision_num=None): |
| 141 """Make sure we have the latest version of of the repo, and build it. We | 154 """Make sure we have the latest version of of the repo, and build it. We |
| 142 begin and end standing in DART_REPO_LOC. | 155 begin and end standing in DART_REPO_LOC. |
| 143 | 156 |
| 144 Args: | 157 Args: |
| 145 suites: The set of suites that we wish to build. | 158 suites: The set of suites that we wish to build. |
| 146 | 159 |
| 147 Returns: | 160 Returns: |
| 148 err_code = 1 if there was a problem building.""" | 161 err_code = 1 if there was a problem building.""" |
| 149 self._Sync(revision_num) | 162 self._Sync(revision_num) |
| 150 if not revision_num: | 163 if not revision_num: |
| 151 revision_num = SearchForRevision() | 164 revision_num = SearchForRevision() |
| 152 | 165 |
| 153 self.current_revision_num = revision_num | 166 self.current_revision_num = revision_num |
| 154 success, stdout, stderr = self.GetArchive('sdk') | 167 success, stdout, stderr = self.GetArchive('sdk') |
| 155 if (not os.path.exists(os.path.join( | 168 if (not os.path.exists(os.path.join( |
| 156 DART_REPO_LOC, 'tools', 'get_archive.py')) or not success | 169 DART_REPO_LOC, 'tools', 'get_archive.py')) or not success |
| 157 or 'InvalidUriError' in stderr or "Couldn't download" in stdout): | 170 or 'InvalidUriError' in stderr or "Couldn't download" in stdout or |
| 171 'Unable to download' in stdout): |
| 158 # Couldn't find the SDK on Google Storage. Build it locally. | 172 # Couldn't find the SDK on Google Storage. Build it locally. |
| 159 | 173 |
| 160 # On Windows, the output directory is marked as "Read Only," which causes | 174 # TODO(efortuna): Currently always building ia32 architecture because we |
| 161 # an error to be thrown when we use shutil.rmtree. This helper function | 175 # don't have test statistics for what's passing on x64. Eliminate arch |
| 162 # changes the permissions so we can still delete the directory. | |
| 163 def on_rm_error(func, path, exc_info): | |
| 164 if os.path.exists(path): | |
| 165 os.chmod(path, stat.S_IWRITE) | |
| 166 os.unlink(path) | |
| 167 # TODO(efortuna): Currently always building ia32 architecture because we | |
| 168 # don't have test statistics for what's passing on x64. Eliminate arch | |
| 169 # specification when we have tests running on x64, too. | 176 # specification when we have tests running on x64, too. |
| 170 shutil.rmtree(os.path.join(os.getcwd(), | 177 shutil.rmtree(os.path.join(os.getcwd(), |
| 171 utils.GetBuildRoot(utils.GuessOS(), 'release', 'ia32')), | 178 utils.GetBuildRoot(utils.GuessOS(), 'release', 'ia32')), |
| 172 onerror=on_rm_error) | 179 onerror=TestRunner._OnRmError) |
| 173 lines = self.RunCmd([os.path.join('.', 'tools', 'build.py'), '-m', | 180 lines = self.RunCmd([os.path.join('.', 'tools', 'build.py'), '-m', |
| 174 'release', '--arch=ia32', 'create_sdk']) | 181 'release', '--arch=ia32', 'create_sdk']) |
| 175 | 182 |
| 176 for line in lines: | 183 for line in lines: |
| 177 if 'BUILD FAILED' in line: | 184 if 'BUILD FAILED' in line: |
| 178 # Someone checked in a broken build! Stop trying to make it work | 185 # Someone checked in a broken build! Stop trying to make it work |
| 179 # and wait to try again. | 186 # and wait to try again. |
| 180 print 'Broken Build' | 187 print 'Broken Build' |
| 181 return 1 | 188 return 1 |
| 182 return 0 | 189 return 0 |
| 183 | 190 |
| 184 def EnsureOutputDirectory(self, dir_name): | 191 def EnsureOutputDirectory(self, dir_name): |
| 185 """Test that the listed directory name exists, and if not, create one for | 192 """Test that the listed directory name exists, and if not, create one for |
| 186 our output to be placed. | 193 our output to be placed. |
| 187 | 194 |
| 188 Args: | 195 Args: |
| 189 dir_name: the directory we will create if it does not exist.""" | 196 dir_name: the directory we will create if it does not exist.""" |
| 190 dir_path = os.path.join(TOP_LEVEL_DIR, 'tools', | 197 dir_path = os.path.join(TOP_LEVEL_DIR, 'tools', |
| 191 'testing', 'perf_testing', dir_name) | 198 'testing', 'perf_testing', dir_name) |
| 192 if not os.path.exists(dir_path): | 199 if not os.path.exists(dir_path): |
| 193 os.makedirs(dir_path) | 200 os.makedirs(dir_path) |
| 194 print 'Creating output directory ', dir_path | 201 print 'Creating output directory ', dir_path |
| 195 | 202 |
| 196 def HasInterestingCode(self, revision_num=None): | 203 def HasInterestingCode(self, revision_num=None): |
| 197 """Tests if there are any versions of files that might change performance | 204 """Tests if there are any versions of files that might change performance |
| 198 results on the server. | 205 results on the server. |
| 199 | 206 |
| 200 Returns: | 207 Returns: |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 else: | 284 else: |
| 278 last_done_cl = int(SearchForRevision(DART_REPO_LOC)) + 1 | 285 last_done_cl = int(SearchForRevision(DART_REPO_LOC)) + 1 |
| 279 while last_done_cl <= latest_interesting_server_rev: | 286 while last_done_cl <= latest_interesting_server_rev: |
| 280 file_list = GetFileList(last_done_cl) | 287 file_list = GetFileList(last_done_cl) |
| 281 if HasPerfAffectingResults(file_list): | 288 if HasPerfAffectingResults(file_list): |
| 282 return (True, last_done_cl) | 289 return (True, last_done_cl) |
| 283 else: | 290 else: |
| 284 UpdateSetOfDoneCls(last_done_cl) | 291 UpdateSetOfDoneCls(last_done_cl) |
| 285 last_done_cl += 1 | 292 last_done_cl += 1 |
| 286 return (False, None) | 293 return (False, None) |
| 287 | 294 |
| 288 def GetOsDirectory(self): | 295 def GetOsDirectory(self): |
| 289 """Specifies the name of the directory for the testing build of dart, which | 296 """Specifies the name of the directory for the testing build of dart, which |
| 290 has yet a different naming convention from utils.getBuildRoot(...).""" | 297 has yet a different naming convention from utils.getBuildRoot(...).""" |
| 291 if platform.system() == 'Windows': | 298 if platform.system() == 'Windows': |
| 292 return 'windows' | 299 return 'windows' |
| 293 elif platform.system() == 'Darwin': | 300 elif platform.system() == 'Darwin': |
| 294 return 'macos' | 301 return 'macos' |
| 295 else: | 302 else: |
| 296 return 'linux' | 303 return 'linux' |
| 297 | 304 |
| 298 def ParseArgs(self): | 305 def ParseArgs(self): |
| 299 parser = optparse.OptionParser() | 306 parser = optparse.OptionParser() |
| 300 parser.add_option('--suites', '-s', dest='suites', help='Run the specified ' | 307 parser.add_option('--suites', '-s', dest='suites', help='Run the specified ' |
| 301 'comma-separated test suites from set: %s' % \ | 308 'comma-separated test suites from set: %s' % \ |
| 302 ','.join(TestBuilder.AvailableSuiteNames()), | 309 ','.join(TestBuilder.AvailableSuiteNames()), |
| 303 action='store', default=None) | 310 action='store', default=None) |
| 304 parser.add_option('--forever', '-f', dest='continuous', help='Run this scri' | 311 parser.add_option('--forever', '-f', dest='continuous', help='Run this scri' |
| 305 'pt forever, always checking for the next svn checkin', | 312 'pt forever, always checking for the next svn checkin', |
| 306 action='store_true', default=False) | 313 action='store_true', default=False) |
| 307 parser.add_option('--nobuild', '-n', dest='no_build', action='store_true', | 314 parser.add_option('--nobuild', '-n', dest='no_build', action='store_true', |
| 308 help='Do not sync with the repository and do not ' | 315 help='Do not sync with the repository and do not ' |
| 309 'rebuild.', default=False) | 316 'rebuild.', default=False) |
| 310 parser.add_option('--noupload', '-u', dest='no_upload', action='store_true', | 317 parser.add_option('--noupload', '-u', dest='no_upload', action='store_true', |
| 311 help='Do not post the results of the run.', default=False) | 318 help='Do not post the results of the run.', default=False) |
| 312 parser.add_option('--notest', '-t', dest='no_test', action='store_true', | 319 parser.add_option('--notest', '-t', dest='no_test', action='store_true', |
| 313 help='Do not run the tests.', default=False) | 320 help='Do not run the tests.', default=False) |
| 314 parser.add_option('--verbose', '-v', dest='verbose', | 321 parser.add_option('--verbose', '-v', dest='verbose', |
| 315 help='Print extra debug output', action='store_true', | 322 help='Print extra debug output', action='store_true', |
| 316 default=False) | 323 default=False) |
| 317 parser.add_option('--backfill', '-b', dest='backfill', | 324 parser.add_option('--backfill', '-b', dest='backfill', |
| 318 help='Backfill earlier CLs with additional results when ' | 325 help='Backfill earlier CLs with additional results when ' |
| 319 'there is idle time.', action='store_true', | 326 'there is idle time.', action='store_true', |
| 320 default=False) | 327 default=False) |
| 321 | 328 |
| 322 args, ignored = parser.parse_args() | 329 args, ignored = parser.parse_args() |
| 323 | 330 |
| 324 if not args.suites: | 331 if not args.suites: |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 # cur_time is used as a timestamp of when this performance test was run. | 402 # cur_time is used as a timestamp of when this performance test was run. |
| 396 self.cur_time = str(time.mktime(datetime.datetime.now().timetuple())) | 403 self.cur_time = str(time.mktime(datetime.datetime.now().timetuple())) |
| 397 self.values_list = values_list | 404 self.values_list = values_list |
| 398 self.platform_list = platform_list | 405 self.platform_list = platform_list |
| 399 self.test_runner = test_runner | 406 self.test_runner = test_runner |
| 400 self.tester = tester | 407 self.tester = tester |
| 401 self.file_processor = file_processor | 408 self.file_processor = file_processor |
| 402 self.revision_dict = dict() | 409 self.revision_dict = dict() |
| 403 self.values_dict = dict() | 410 self.values_dict = dict() |
| 404 self.extra_metrics = extra_metrics | 411 self.extra_metrics = extra_metrics |
| 405 # Initialize our values store.» » | 412 # Initialize our values store. |
| 406 for platform in platform_list:» » | 413 for platform in platform_list: |
| 407 self.revision_dict[platform] = dict()» » | 414 self.revision_dict[platform] = dict() |
| 408 self.values_dict[platform] = dict()» » | 415 self.values_dict[platform] = dict() |
| 409 for f in variants:» » | 416 for f in variants: |
| 410 self.revision_dict[platform][f] = dict()» » | 417 self.revision_dict[platform][f] = dict() |
| 411 self.values_dict[platform][f] = dict()» » | 418 self.values_dict[platform][f] = dict() |
| 412 for val in values_list:»» | 419 for val in values_list: |
| 413 self.revision_dict[platform][f][val] = []» » | 420 self.revision_dict[platform][f][val] = [] |
| 414 self.values_dict[platform][f][val] = []» » | 421 self.values_dict[platform][f][val] = [] |
| 415 for extra_metric in extra_metrics:» » | 422 for extra_metric in extra_metrics: |
| 416 self.revision_dict[platform][f][extra_metric] = []» » | 423 self.revision_dict[platform][f][extra_metric] = [] |
| 417 self.values_dict[platform][f][extra_metric] = [] | 424 self.values_dict[platform][f][extra_metric] = [] |
| 418 | 425 |
| 419 def IsValidCombination(self, platform, variant): | 426 def IsValidCombination(self, platform, variant): |
| 420 """Check whether data should be captured for this platform/variant | 427 """Check whether data should be captured for this platform/variant |
| 421 combination. | 428 combination. |
| 422 """ | 429 """ |
| 423 # TODO(vsm): This avoids a bug in 32-bit Chrome (dartium) | 430 if platform == 'dartium' and (variant == 'js' or variant == 'dart2js_html'): |
| 424 # running JS dromaeo. | 431 # Testing JavaScript performance on Dartium is a waste of time. Should be |
| 425 if platform == 'dartium' and variant == 'js': | 432 # same as Chrome. |
| 426 return False | 433 return False |
| 427 if (platform == 'safari' and variant == 'dart2js' and | 434 if (platform == 'safari' and variant == 'dart2js' and |
| 428 int(self.test_runner.current_revision_num) < 10193): | 435 int(self.test_runner.current_revision_num) < 10193): |
| 429 # In revision 10193 we fixed a bug that allows Safari 6 to run dart2js | 436 # In revision 10193 we fixed a bug that allows Safari 6 to run dart2js |
| 430 # code. Since we can't change the Safari version on the machine, we're | 437 # code. Since we can't change the Safari version on the machine, we're |
| 431 # just not running | 438 # just not running |
| 432 # for this case. | 439 # for this case. |
| 433 return False | 440 return False |
| 434 return True | 441 return True |
| 435 | 442 |
| 436 def Run(self): | 443 def Run(self): |
| 437 """Run the benchmarks/tests from the command line and plot the | 444 """Run the benchmarks/tests from the command line and plot the |
| 438 results. | 445 results. |
| 439 """ | 446 """ |
| 440 for visitor in [self.tester, self.file_processor]: | 447 for visitor in [self.tester, self.file_processor]: |
| 441 visitor.Prepare() | 448 visitor.Prepare() |
| 442 | 449 |
| 443 os.chdir(TOP_LEVEL_DIR) | 450 os.chdir(TOP_LEVEL_DIR) |
| 444 self.test_runner.EnsureOutputDirectory(self.result_folder_name) | 451 self.test_runner.EnsureOutputDirectory(self.result_folder_name) |
| 445 self.test_runner.EnsureOutputDirectory(os.path.join( | 452 self.test_runner.EnsureOutputDirectory(os.path.join( |
| 446 'old', self.result_folder_name)) | 453 'old', self.result_folder_name)) |
| 447 os.chdir(DART_REPO_LOC) | 454 os.chdir(DART_REPO_LOC) |
| 448 if not self.test_runner.no_test: | 455 if not self.test_runner.no_test: |
| 449 self.tester.RunTests() | 456 self.tester.RunTests() |
| 450 | 457 |
| 451 os.chdir(os.path.join(TOP_LEVEL_DIR, 'tools', 'testing', 'perf_testing')) | 458 os.chdir(os.path.join(TOP_LEVEL_DIR, 'tools', 'testing', 'perf_testing')) |
| 452 | 459 |
| 453 files = os.listdir(self.result_folder_name) | 460 files = os.listdir(self.result_folder_name) |
| 454 post_success = True | 461 post_success = True |
| 455 for afile in files: | 462 for afile in files: |
| 456 if not afile.startswith('.'): | 463 if not afile.startswith('.'): |
| 457 should_move_file = self.file_processor.ProcessFile(afile, True) | 464 should_move_file = self.file_processor.ProcessFile(afile, True) |
| 458 if should_move_file: | 465 if should_move_file: |
| 459 shutil.move(os.path.join(self.result_folder_name, afile), | 466 shutil.move(os.path.join(self.result_folder_name, afile), |
| 460 os.path.join('old', self.result_folder_name, afile)) | 467 os.path.join('old', self.result_folder_name, afile)) |
| 461 else: | 468 else: |
| 462 post_success = False | 469 post_success = False |
| 463 | 470 |
| 464 return post_success | 471 return post_success |
| 465 | 472 |
| 466 | 473 |
| 467 class Tester(object): | 474 class Tester(object): |
| 468 """The base level visitor class that runs tests. It contains convenience | 475 """The base level visitor class that runs tests. It contains convenience |
| 469 methods that many Tester objects use. Any class that would like to be a | 476 methods that many Tester objects use. Any class that would like to be a |
| 470 TesterVisitor must implement the RunTests() method.""" | 477 TesterVisitor must implement the RunTests() method.""" |
| 471 | 478 |
| 472 def __init__(self, test): | 479 def __init__(self, test): |
| 473 self.test = test | 480 self.test = test |
| 474 | 481 |
| 475 def Prepare(self): | 482 def Prepare(self): |
| 476 """Perform any initial setup required before the test is run.""" | 483 """Perform any initial setup required before the test is run.""" |
| 477 pass | 484 pass |
| 478 | 485 |
| 479 def AddSvnRevisionToTrace(self, outfile, browser = None): | 486 def AddSvnRevisionToTrace(self, outfile, browser = None): |
| 480 """Add the svn version number to the provided tracefile.""" | 487 """Add the svn version number to the provided tracefile.""" |
| 481 def get_dartium_revision(): | 488 def get_dartium_revision(): |
| 482 version_file_name = os.path.join(DART_REPO_LOC, 'client', 'tests', | 489 version_file_name = os.path.join(DART_REPO_LOC, 'client', 'tests', |
| 483 'dartium', 'LAST_VERSION') | 490 'dartium', 'LAST_VERSION') |
| 484 version_file = open(version_file_name, 'r') | 491 try: |
| 485 version = version_file.read().split('.')[-2] | 492 version_file = open(version_file_name, 'r') |
| 486 version_file.close() | 493 version = version_file.read().split('.')[-3].split('-')[-1] |
| 487 return version | 494 version_file.close() |
| 495 return version |
| 496 except IOError as e: |
| 497 dartium_dir = os.path.join(DART_REPO_LOC, 'client', 'tests', 'dartium') |
| 498 if (os.path.exists(os.path.join(dartium_dir, 'Chromium.app', 'Contents', |
| 499 'MacOS', 'Chromium') or os.path.exists(os.path.join(dartium_dir, |
| 500 'chrome.exe'))) or |
| 501 os.path.exists(os.path.join(dartium_dir, 'chrome'))): |
| 502 print "Error: VERSION file wasn't found." |
| 503 return SearchForRevision() |
| 504 else: |
| 505 raise |
| 488 | 506 |
| 489 if browser and browser == 'dartium': | 507 if browser and browser == 'dartium': |
| 490 revision = get_dartium_revision() | 508 revision = get_dartium_revision() |
| 491 self.test.test_runner.RunCmd(['echo', 'Revision: ' + revision], outfile) | 509 self.test.test_runner.RunCmd(['echo', 'Revision: ' + revision], outfile) |
| 492 else: | 510 else: |
| 493 revision = SearchForRevision() | 511 revision = SearchForRevision() |
| 494 self.test.test_runner.RunCmd(['echo', 'Revision: ' + revision], outfile) | 512 self.test.test_runner.RunCmd(['echo', 'Revision: ' + revision], outfile) |
| 495 | 513 |
| 496 | 514 |
| 497 class Processor(object): | 515 class Processor(object): |
| 498 """The base level vistor class that processes tests. It contains convenience | 516 """The base level vistor class that processes tests. It contains convenience |
| 499 methods that many File Processor objects use. Any class that would like to be | 517 methods that many File Processor objects use. Any class that would like to be |
| 500 a ProcessorVisitor must implement the ProcessFile() method.""" | 518 a ProcessorVisitor must implement the ProcessFile() method.""" |
| 501 | 519 |
| 502 SCORE = 'Score' | 520 SCORE = 'Score' |
| 503 COMPILE_TIME = 'CompileTime' | 521 COMPILE_TIME = 'CompileTime' |
| 504 CODE_SIZE = 'CodeSize' | 522 CODE_SIZE = 'CodeSize' |
| 505 | 523 |
| 506 def __init__(self, test): | 524 def __init__(self, test): |
| 507 self.test = test | 525 self.test = test |
| 508 | 526 |
| 509 def Prepare(self): | 527 def Prepare(self): |
| 510 """Perform any initial setup required before the test is run.""" | 528 """Perform any initial setup required before the test is run.""" |
| 511 pass | 529 pass |
| 512 | 530 |
| 513 def OpenTraceFile(self, afile, not_yet_uploaded): | 531 def OpenTraceFile(self, afile, not_yet_uploaded): |
| 514 """Find the correct location for the trace file, and open it. | 532 """Find the correct location for the trace file, and open it. |
| 515 Args: | 533 Args: |
| 516 afile: The tracefile name. | 534 afile: The tracefile name. |
| 517 not_yet_uploaded: True if this file is to be found in a directory that | 535 not_yet_uploaded: True if this file is to be found in a directory that |
| 518 contains un-uploaded data. | 536 contains un-uploaded data. |
| 519 Returns: A file object corresponding to the given file name.""" | 537 Returns: A file object corresponding to the given file name.""" |
| 520 file_path = os.path.join(self.test.result_folder_name, afile) | 538 file_path = os.path.join(self.test.result_folder_name, afile) |
| 521 if not not_yet_uploaded: | 539 if not not_yet_uploaded: |
| 522 file_path = os.path.join('old', file_path) | 540 file_path = os.path.join('old', file_path) |
| 523 return open(file_path) | 541 return open(file_path) |
| 524 | 542 |
| 525 def ReportResults(self, benchmark_name, score, platform, variant, | 543 def ReportResults(self, benchmark_name, score, platform, variant, |
| 526 revision_number, metric): | 544 revision_number, metric): |
| 527 """Store the results of the benchmark run. | 545 """Store the results of the benchmark run. |
| 528 Args: | 546 Args: |
| 529 benchmark_name: The name of the individual benchmark. | 547 benchmark_name: The name of the individual benchmark. |
| 530 score: The numerical value of this benchmark. | 548 score: The numerical value of this benchmark. |
| 531 platform: The platform the test was run on (firefox, command line, etc). | 549 platform: The platform the test was run on (firefox, command line, etc). |
| 532 variant: Specifies whether the data was about generated Frog, js, a | 550 variant: Specifies whether the data was about generated Frog, js, a |
| 533 combination of both, or Dart depending on the test. | 551 combination of both, or Dart depending on the test. |
| 534 revision_number: The revision of the code (and sometimes the revision of | 552 revision_number: The revision of the code (and sometimes the revision of |
| 535 dartium). | 553 dartium). |
| 536 | 554 |
| 537 Returns: True if the post was successful file.""" | 555 Returns: True if the post was successful file.""" |
| 538 return post_results.report_results(benchmark_name, score, platform, variant, | 556 return post_results.report_results(benchmark_name, score, platform, variant, |
| 539 revision_number, metric) | 557 revision_number, metric) |
| 540 | 558 |
| 541 def CalculateGeometricMean(self, platform, variant, svn_revision): | 559 def CalculateGeometricMean(self, platform, variant, svn_revision): |
| 542 """Calculate the aggregate geometric mean for JS and dart2js benchmark sets, | 560 """Calculate the aggregate geometric mean for JS and dart2js benchmark sets, |
| 543 given two benchmark dictionaries.""" | 561 given two benchmark dictionaries.""" |
| 544 geo_mean = 0» » | 562 geo_mean = 0 |
| 545 if self.test.IsValidCombination(platform, variant): | 563 if self.test.IsValidCombination(platform, variant): |
| 546 for benchmark in self.test.values_list: | 564 for benchmark in self.test.values_list: |
| 547 if not self.test.values_dict[platform][variant][benchmark]: | 565 if not self.test.values_dict[platform][variant][benchmark]: |
| 548 print 'Error determining mean for %s %s %s' % (platform, variant, | 566 print 'Error determining mean for %s %s %s' % (platform, variant, |
| 549 benchmark) | 567 benchmark) |
| 550 continue | 568 continue |
| 551 geo_mean += math.log( | 569 geo_mean += math.log( |
| 552 self.test.values_dict[platform][variant][benchmark][-1]) | 570 self.test.values_dict[platform][variant][benchmark][-1]) |
| 553 | 571 |
| 554 self.test.values_dict[platform][variant]['Geo-Mean'] += \ | 572 self.test.values_dict[platform][variant]['Geo-Mean'] += \ |
| (...skipping 27 matching lines...) Expand all Loading... |
| 582 file_processor: The visitor that processes files in the format | 600 file_processor: The visitor that processes files in the format |
| 583 appropriate for this test. | 601 appropriate for this test. |
| 584 extra_metrics: A list of any additional measurements we wish to keep | 602 extra_metrics: A list of any additional measurements we wish to keep |
| 585 track of (such as the geometric mean of a set, the sum, etc).""" | 603 track of (such as the geometric mean of a set, the sum, etc).""" |
| 586 super(RuntimePerformanceTest, self).__init__(result_folder_name, | 604 super(RuntimePerformanceTest, self).__init__(result_folder_name, |
| 587 platform_list, versions, benchmarks, test_runner, tester, | 605 platform_list, versions, benchmarks, test_runner, tester, |
| 588 file_processor) | 606 file_processor) |
| 589 self.platform_list = platform_list | 607 self.platform_list = platform_list |
| 590 self.platform_type = platform_type | 608 self.platform_type = platform_type |
| 591 self.versions = versions | 609 self.versions = versions |
| 592 self.benchmarks = benchmarks | 610 self.benchmarks = benchmarks |
| 593 | 611 |
| 594 | 612 |
| 595 class BrowserTester(Tester): | 613 class BrowserTester(Tester): |
| 596 @staticmethod | 614 @staticmethod |
| 597 def GetBrowsers(add_dartium=True): | 615 def GetBrowsers(add_dartium=True): |
| 598 browsers = ['ff', 'chrome'] | 616 browsers = ['ff', 'chrome'] |
| 599 if add_dartium: | 617 if add_dartium: |
| 600 browsers += ['dartium'] | 618 browsers += ['dartium'] |
| 601 has_shell = False | 619 has_shell = False |
| 602 if platform.system() == 'Darwin': | 620 if platform.system() == 'Darwin': |
| 603 browsers += ['safari'] | 621 browsers += ['safari'] |
| 604 if platform.system() == 'Windows': | 622 if platform.system() == 'Windows': |
| 605 browsers += ['ie'] | 623 browsers += ['ie'] |
| 606 has_shell = True | 624 has_shell = True |
| 607 return browsers | 625 return browsers |
| 608 | 626 |
| 609 | 627 |
| 610 class CommonBrowserTest(RuntimePerformanceTest): | 628 class CommonBrowserTest(RuntimePerformanceTest): |
| 611 """Runs this basic performance tests (Benchpress, some V8 benchmarks) in the | 629 """Runs this basic performance tests (Benchpress, some V8 benchmarks) in the |
| 612 browser.""" | 630 browser.""" |
| 613 | 631 |
| 614 def __init__(self, test_runner): | 632 def __init__(self, test_runner): |
| 615 """Args: | 633 """Args: |
| 616 test_runner: Reference to the object that notifies us when to run.""" | 634 test_runner: Reference to the object that notifies us when to run.""" |
| 617 super(CommonBrowserTest, self).__init__( | 635 super(CommonBrowserTest, self).__init__( |
| 618 self.Name(), BrowserTester.GetBrowsers(False), | 636 self.Name(), BrowserTester.GetBrowsers(False), |
| 619 'browser', ['js', 'dart2js'], | 637 'browser', ['js', 'dart2js'], |
| 620 self.GetStandaloneBenchmarks(), test_runner, | 638 self.GetStandaloneBenchmarks(), test_runner, |
| 621 self.CommonBrowserTester(self), | 639 self.CommonBrowserTester(self), |
| 622 self.CommonBrowserFileProcessor(self)) | 640 self.CommonBrowserFileProcessor(self)) |
| 623 | 641 |
| 624 @staticmethod | 642 @staticmethod |
| 625 def Name(): | 643 def Name(): |
| 626 return 'browser-perf' | 644 return 'browser-perf' |
| 627 | 645 |
| 628 @staticmethod | 646 @staticmethod |
| 629 def GetStandaloneBenchmarks(): | 647 def GetStandaloneBenchmarks(): |
| 630 return ['Mandelbrot', 'DeltaBlue', 'Richards', 'NBody', 'BinaryTrees', | 648 return ['Mandelbrot', 'DeltaBlue', 'Richards', 'NBody', 'BinaryTrees', |
| 631 'Fannkuch', 'Meteor', 'BubbleSort', 'Fibonacci', 'Loop', 'Permute', | 649 'Fannkuch', 'Meteor', 'BubbleSort', 'Fibonacci', 'Loop', 'Permute', |
| 632 'Queens', 'QuickSort', 'Recurse', 'Sieve', 'Sum', 'Tak', 'Takl', 'Towers', | 650 'Queens', 'QuickSort', 'Recurse', 'Sieve', 'Sum', 'Tak', 'Takl', 'Towers', |
| 633 'TreeSort'] | 651 'TreeSort'] |
| (...skipping 12 matching lines...) Expand all Loading... |
| 646 continue | 664 continue |
| 647 self.test.trace_file = os.path.join(TOP_LEVEL_DIR, | 665 self.test.trace_file = os.path.join(TOP_LEVEL_DIR, |
| 648 'tools', 'testing', 'perf_testing', self.test.result_folder_name, | 666 'tools', 'testing', 'perf_testing', self.test.result_folder_name, |
| 649 'perf-%s-%s-%s' % (self.test.cur_time, browser, version)) | 667 'perf-%s-%s-%s' % (self.test.cur_time, browser, version)) |
| 650 self.AddSvnRevisionToTrace(self.test.trace_file, browser) | 668 self.AddSvnRevisionToTrace(self.test.trace_file, browser) |
| 651 file_path = os.path.join( | 669 file_path = os.path.join( |
| 652 os.getcwd(), 'internal', 'browserBenchmarks', 'V8vDart', | 670 os.getcwd(), 'internal', 'browserBenchmarks', 'V8vDart', |
| 653 'V8vDart_page_%s.html' % version) | 671 'V8vDart_page_%s.html' % version) |
| 654 self.test.test_runner.RunCmd( | 672 self.test.test_runner.RunCmd( |
| 655 ['python', os.path.join('tools', 'testing', 'run_selenium.py'), | 673 ['python', os.path.join('tools', 'testing', 'run_selenium.py'), |
| 656 '--out', file_path, '--browser', browser, | 674 '--out', '"file:///%s"' % file_path, '--browser', browser, |
| 657 '--timeout', '600', '--mode', 'perf'], self.test.trace_file, | 675 '--timeout', '600', '--mode', 'perf'], self.test.trace_file, |
| 658 append=True) | 676 append=True) |
| 659 | 677 |
| 660 class CommonBrowserFileProcessor(Processor): | 678 class CommonBrowserFileProcessor(Processor): |
| 661 | 679 |
| 662 def ProcessFile(self, afile, should_post_file): | 680 def ProcessFile(self, afile, should_post_file): |
| 663 """Comb through the html to find the performance results. | 681 """Comb through the html to find the performance results. |
| 664 Returns: True if we successfully posted our data to storage and/or we can | 682 Returns: True if we successfully posted our data to storage and/or we can |
| 665 delete the trace file.""" | 683 delete the trace file.""" |
| 666 os.chdir(os.path.join(TOP_LEVEL_DIR, 'tools', | 684 os.chdir(os.path.join(TOP_LEVEL_DIR, 'tools', |
| 667 'testing', 'perf_testing')) | 685 'testing', 'perf_testing')) |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 'getElementsByName', | 759 'getElementsByName', |
| 742 'getElementsByName (not in document)']), | 760 'getElementsByName (not in document)']), |
| 743 'traverse': ('traverse', [ | 761 'traverse': ('traverse', [ |
| 744 'firstChild', | 762 'firstChild', |
| 745 'lastChild', | 763 'lastChild', |
| 746 'nextSibling', | 764 'nextSibling', |
| 747 'previousSibling', | 765 'previousSibling', |
| 748 'childNodes']) | 766 'childNodes']) |
| 749 } | 767 } |
| 750 | 768 |
| 751 # Use filenames that don't have unusual characters for benchmark names.» | 769 # Use filenames that don't have unusual characters for benchmark names. |
| 752 @staticmethod» | 770 @staticmethod |
| 753 def LegalizeFilename(str): | 771 def LegalizeFilename(str): |
| 754 remap = {» | 772 remap = { |
| 755 ' ': '_',» | 773 ' ': '_', |
| 756 '(': '_',» | 774 '(': '_', |
| 757 ')': '_',» | 775 ')': '_', |
| 758 '*': 'ALL',» | 776 '*': 'ALL', |
| 759 '=': 'ASSIGN',» | 777 '=': 'ASSIGN', |
| 760 }» | 778 } |
| 761 for (old, new) in remap.iteritems():» | 779 for (old, new) in remap.iteritems(): |
| 762 str = str.replace(old, new) | 780 str = str.replace(old, new) |
| 763 return str | 781 return str |
| 764 | 782 |
| 765 # TODO(vsm): This is a hack to skip breaking tests. Triage this | 783 # TODO(vsm): This is a hack to skip breaking tests. Triage this |
| 766 # failure properly. The modify suite fails on 32-bit chrome, which | 784 # failure properly. The modify suite fails on 32-bit chrome, which |
| 767 # is the default on mac and win. | 785 # is the default on mac and win. |
| 768 @staticmethod | 786 @staticmethod |
| 769 def GetValidDromaeoTags(): | 787 def GetValidDromaeoTags(): |
| 770 tags = [tag for (tag, _) in DromaeoTester.DROMAEO_BENCHMARKS.values()] | 788 tags = [tag for (tag, _) in DromaeoTester.DROMAEO_BENCHMARKS.values()] |
| 771 if platform.system() == 'Darwin' or platform.system() == 'Windows': | 789 if platform.system() == 'Darwin' or platform.system() == 'Windows': |
| 772 tags.remove('modify') | 790 tags.remove('modify') |
| 773 return tags | 791 return tags |
| 774 | 792 |
| 775 @staticmethod | 793 @staticmethod |
| 776 def GetDromaeoBenchmarks(): | 794 def GetDromaeoBenchmarks(): |
| 777 valid = DromaeoTester.GetValidDromaeoTags() | 795 valid = DromaeoTester.GetValidDromaeoTags() |
| 778 benchmarks = reduce(lambda l1,l2: l1+l2, | 796 benchmarks = reduce(lambda l1,l2: l1+l2, |
| 779 [tests for (tag, tests) in | 797 [tests for (tag, tests) in |
| 780 DromaeoTester.DROMAEO_BENCHMARKS.values() | 798 DromaeoTester.DROMAEO_BENCHMARKS.values() |
| 781 if tag in valid]) | 799 if tag in valid]) |
| 782 return map(DromaeoTester.LegalizeFilename, benchmarks) | 800 return map(DromaeoTester.LegalizeFilename, benchmarks) |
| 783 | 801 |
| 784 @staticmethod | 802 @staticmethod |
| 785 def GetDromaeoVersions(): | 803 def GetDromaeoVersions(): |
| 786 return ['js', 'dart2js_html'] | 804 return ['js', 'dart2js_html', 'dart_html'] |
| 787 | 805 |
| 788 | 806 |
| 789 class DromaeoTest(RuntimePerformanceTest): | 807 class DromaeoTest(RuntimePerformanceTest): |
| 790 """Runs Dromaeo tests, in the browser.""" | 808 """Runs Dromaeo tests, in the browser.""" |
| 791 def __init__(self, test_runner): | 809 def __init__(self, test_runner): |
| 792 super(DromaeoTest, self).__init__( | 810 super(DromaeoTest, self).__init__( |
| 793 self.Name(), | 811 self.Name(), |
| 794 BrowserTester.GetBrowsers(True), | 812 BrowserTester.GetBrowsers(True), |
| 795 'browser', | 813 'browser', |
| 796 DromaeoTester.GetDromaeoVersions(), | 814 DromaeoTester.GetDromaeoVersions(), |
| 797 DromaeoTester.GetDromaeoBenchmarks(), test_runner, | 815 DromaeoTester.GetDromaeoBenchmarks(), test_runner, |
| 798 self.DromaeoPerfTester(self), | 816 self.DromaeoPerfTester(self), |
| 799 self.DromaeoFileProcessor(self)) | 817 self.DromaeoFileProcessor(self)) |
| 800 | 818 |
| 801 @staticmethod | 819 @staticmethod |
| 802 def Name(): | 820 def Name(): |
| 803 return 'dromaeo' | 821 return 'dromaeo' |
| 804 | 822 |
| 805 class DromaeoPerfTester(DromaeoTester): | 823 class DromaeoPerfTester(DromaeoTester): |
| 806 def MoveChromeDriverIfNeeded(self, browser): | 824 def MoveChromeDriverIfNeeded(self, browser): |
| 807 """Move the appropriate version of ChromeDriver onto the path. | 825 """Move the appropriate version of ChromeDriver onto the path. |
| 808 TODO(efortuna): This is a total hack because the latest version of Chrome | 826 TODO(efortuna): This is a total hack because the latest version of Chrome |
| 809 (Dartium builds) requires a different version of ChromeDriver, that is | 827 (Dartium builds) requires a different version of ChromeDriver, that is |
| 810 incompatible with the release or beta Chrome and vice versa. Remove these | 828 incompatible with the release or beta Chrome and vice versa. Remove these |
| 811 shenanigans once we're back to both versions of Chrome using the same | 829 shenanigans once we're back to both versions of Chrome using the same |
| 812 version of ChromeDriver. IMPORTANT NOTE: This assumes your chromedriver is | 830 version of ChromeDriver. IMPORTANT NOTE: This assumes your chromedriver is |
| 813 in the default location (inside depot_tools). | 831 in the default location (inside depot_tools). |
| 814 | 832 |
| 815 Returns: True if we were successfully able to download a new version of | 833 Returns: True if we were successfully able to download a new version of |
| 816 chromedriver and/or move the correct chromedriver into position. | 834 chromedriver and/or move the correct chromedriver into position. |
| 817 """ | 835 """ |
| (...skipping 28 matching lines...) Expand all Loading... |
| 846 if not os.path.exists(os.path.dirname(from_dir)): | 864 if not os.path.exists(os.path.dirname(from_dir)): |
| 847 os.makedirs(os.path.dirname(from_dir)) | 865 os.makedirs(os.path.dirname(from_dir)) |
| 848 shutil.copyfile(from_dir, to_dir) | 866 shutil.copyfile(from_dir, to_dir) |
| 849 | 867 |
| 850 for loc in path: | 868 for loc in path: |
| 851 if 'depot_tools' in loc: | 869 if 'depot_tools' in loc: |
| 852 if browser == 'chrome': | 870 if browser == 'chrome': |
| 853 if os.path.exists(orig_chromedriver_path): | 871 if os.path.exists(orig_chromedriver_path): |
| 854 MoveChromedriver(loc) | 872 MoveChromedriver(loc) |
| 855 elif browser == 'dartium': | 873 elif browser == 'dartium': |
| 856 if (int(self.test.test_runner.current_revision_num) < | 874 if (int(self.test.test_runner.current_revision_num) < |
| 857 FIRST_CHROMEDRIVER): | 875 FIRST_CHROMEDRIVER): |
| 858 # If we don't have a stashed a different chromedriver just use | 876 # If we don't have a stashed different chromedriver just use |
| 859 # the regular chromedriver. | 877 # the regular chromedriver. |
| 860 if not os.path.exists(os.path.dirname(orig_chromedriver_path)): | 878 if not os.path.exists(os.path.dirname(orig_chromedriver_path)): |
| 861 os.makedirs(os.path.dirname(orig_chromedriver_path)) | 879 os.makedirs(os.path.dirname(orig_chromedriver_path)) |
| 862 self.test.test_runner.RunCmd([os.path.join( | 880 self.test.test_runner.RunCmd([os.path.join( |
| 863 TOP_LEVEL_DIR, 'tools', 'testing', 'webdriver_test_setup.py'), | 881 TOP_LEVEL_DIR, 'tools', 'testing', 'webdriver_test_setup.py'), |
| 864 '-f', '-p', '-s']) | 882 '-f', '-p', '-s']) |
| 865 elif not os.path.exists(dartium_chromedriver_path): | 883 elif not os.path.exists(dartium_chromedriver_path): |
| 866 success, _, _ = self.test.test_runner.GetArchive('chromedriver') | 884 success, _, _ = self.test.test_runner.GetArchive('chromedriver') |
| 867 if not success: | 885 if not success: |
| 868 return False | 886 return False |
| 869 # Move original chromedriver for storage. | 887 # Move original chromedriver for storage. |
| 870 if not os.path.exists(orig_chromedriver_path): | 888 if not os.path.exists(orig_chromedriver_path): |
| 871 MoveChromedriver(loc, copy_to_depot_tools_dir=False) | 889 MoveChromedriver(loc, copy_to_depot_tools_dir=False) |
| 872 if self.test.test_runner.current_revision_num >= FIRST_CHROMEDRIVER: | 890 if self.test.test_runner.current_revision_num >= FIRST_CHROMEDRIVER: |
| 873 # Copy Dartium chromedriver into depot_tools | 891 # Copy Dartium chromedriver into depot_tools |
| 874 MoveChromedriver(loc, from_path=os.path.join( | 892 MoveChromedriver(loc, from_path=os.path.join( |
| 875 dartium_chromedriver_path, 'chromedriver')) | 893 dartium_chromedriver_path, 'chromedriver')) |
| 876 os.chdir(current_dir) | 894 os.chdir(current_dir) |
| 877 return True | 895 return True |
| 878 | 896 |
| 879 def RunTests(self): | 897 def RunTests(self): |
| 880 """Run dromaeo in the browser.""" | 898 """Run dromaeo in the browser.""" |
| 881 | |
| 882 success, _, _ = self.test.test_runner.GetArchive('dartium') | 899 success, _, _ = self.test.test_runner.GetArchive('dartium') |
| 883 if not success: | 900 if not success: |
| 884 # Unable to download dartium. Try later. | 901 # Unable to download dartium. Try later. |
| 885 return | 902 return |
| 886 | 903 |
| 887 # Build tests. | 904 # Build tests. |
| 888 dromaeo_path = os.path.join('samples', 'third_party', 'dromaeo') | 905 dromaeo_path = os.path.join('samples', 'third_party', 'dromaeo') |
| 889 current_path = os.getcwd() | 906 current_path = os.getcwd() |
| 890 os.chdir(dromaeo_path) | 907 os.chdir(dromaeo_path) |
| 891 if os.path.exists('generate_dart2js_tests.py'): | 908 if os.path.exists('generate_dart2js_tests.py'): |
| (...skipping 13 matching lines...) Expand all Loading... |
| 905 return | 922 return |
| 906 for version_name in versions: | 923 for version_name in versions: |
| 907 if not self.test.IsValidCombination(browser, version_name): | 924 if not self.test.IsValidCombination(browser, version_name): |
| 908 continue | 925 continue |
| 909 version = DromaeoTest.DromaeoPerfTester.GetDromaeoUrlQuery( | 926 version = DromaeoTest.DromaeoPerfTester.GetDromaeoUrlQuery( |
| 910 browser, version_name) | 927 browser, version_name) |
| 911 self.test.trace_file = os.path.join(TOP_LEVEL_DIR, | 928 self.test.trace_file = os.path.join(TOP_LEVEL_DIR, |
| 912 'tools', 'testing', 'perf_testing', self.test.result_folder_name, | 929 'tools', 'testing', 'perf_testing', self.test.result_folder_name, |
| 913 'dromaeo-%s-%s-%s' % (self.test.cur_time, browser, version_name)) | 930 'dromaeo-%s-%s-%s' % (self.test.cur_time, browser, version_name)) |
| 914 self.AddSvnRevisionToTrace(self.test.trace_file, browser) | 931 self.AddSvnRevisionToTrace(self.test.trace_file, browser) |
| 915 file_path = '"%s"' % os.path.join(os.getcwd(), dromaeo_path, | 932 file_path = os.path.join(os.getcwd(), dromaeo_path, |
| 916 'index-js.html?%s' % version) | 933 'index%s.html?%s' % ( |
| 934 '' if version_name == 'dart_html' else '-js', version)) |
| 917 self.test.test_runner.RunCmd( | 935 self.test.test_runner.RunCmd( |
| 918 ['python', os.path.join('tools', 'testing', 'run_selenium.py'), | 936 ['python', os.path.join('tools', 'testing', 'run_selenium.py'), |
| 919 '--out', file_path, '--browser', browser, | 937 '--out', '"file:///%s"' % file_path, '--browser', browser, |
| 920 '--timeout', '900', '--mode', 'dromaeo'], self.test.trace_file, | 938 '--timeout', '900', '--mode', 'dromaeo'], self.test.trace_file, |
| 921 append=True) | 939 append=True) |
| 922 # Put default Chromedriver back in. | 940 # Put default Chromedriver back in. |
| 923 self.MoveChromeDriverIfNeeded('chrome') | 941 self.MoveChromeDriverIfNeeded('chrome') |
| 924 | 942 |
| 925 @staticmethod | 943 @staticmethod |
| 926 def GetDromaeoUrlQuery(browser, version): | 944 def GetDromaeoUrlQuery(browser, version): |
| 927 if browser == 'dartium': | 945 if browser == 'dartium': |
| 928 version = version.replace('frog', 'dart') | 946 version = version.replace('frog', 'dart') |
| 929 version = version.replace('_','AND') | 947 version = version.replace('_','AND') |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1035 result_set.add(revision_num) | 1053 result_set.add(revision_num) |
| 1036 pickle.dump(result_set, f) | 1054 pickle.dump(result_set, f) |
| 1037 f.close() | 1055 f.close() |
| 1038 return result_set | 1056 return result_set |
| 1039 | 1057 |
| 1040 | 1058 |
| 1041 def FillInBackHistory(results_set, runner): | 1059 def FillInBackHistory(results_set, runner): |
| 1042 """Fill in back history performance data. This is done one of two ways, with | 1060 """Fill in back history performance data. This is done one of two ways, with |
| 1043 equal probability of trying each way (falling back on the sequential version | 1061 equal probability of trying each way (falling back on the sequential version |
| 1044 as our data becomes more densely populated).""" | 1062 as our data becomes more densely populated).""" |
| 1063 revision_num = int(SearchForRevision(DART_REPO_LOC)) |
| 1045 has_run_extra = False | 1064 has_run_extra = False |
| 1046 revision_num = int(SearchForRevision(DART_REPO_LOC)) | |
| 1047 | 1065 |
| 1048 def TryToRunAdditional(revision_number): | 1066 def TryToRunAdditional(revision_number): |
| 1049 """Determine the number of results we have stored for a particular revision | 1067 """Determine the number of results we have stored for a particular revision |
| 1050 number, and if it is less than 10, run some extra tests. | 1068 number, and if it is less than 10, run some extra tests. |
| 1051 Args: | 1069 Args: |
| 1052 - revision_number: the revision whose performance we want to potentially | 1070 - revision_number: the revision whose performance we want to potentially |
| 1053 test. | 1071 test. |
| 1054 Returns: True if we successfully ran some additional tests.""" | 1072 Returns: True if we successfully ran some additional tests.""" |
| 1055 if not runner.HasInterestingCode(revision_number)[0]: | 1073 if not runner.HasInterestingCode(revision_number)[0]: |
| 1056 results_set = UpdateSetOfDoneCls(revision_number) | 1074 results_set = UpdateSetOfDoneCls(revision_number) |
| 1057 return False | 1075 return False |
| 1058 a_test = TestBuilder.MakeTest(runner.suite_names[0], runner) | 1076 a_test = TestBuilder.MakeTest(runner.suite_names[0], runner) |
| 1059 benchmark_name = a_test.values_list[0] | 1077 benchmark_name = a_test.values_list[0] |
| 1060 platform_name = a_test.platform_list[0] | 1078 platform_name = a_test.platform_list[0] |
| 1061 variant = a_test.values_dict[platform_name].keys()[0] | 1079 variant = a_test.values_dict[platform_name].keys()[0] |
| 1062 num_results = post_results.get_num_results(benchmark_name, | 1080 num_results = post_results.get_num_results(benchmark_name, |
| 1063 platform_name, variant, revision_number, | 1081 platform_name, variant, revision_number, |
| 1064 a_test.file_processor.GetScoreType(benchmark_name)) | 1082 a_test.file_processor.GetScoreType(benchmark_name)) |
| 1065 if num_results < 10: | 1083 if num_results < 10: |
| 1066 # Run at most two more times. | 1084 # Run at most two more times. |
| 1067 if num_results > 8: | 1085 if num_results > 8: |
| 1068 reruns = 10 - num_results | 1086 reruns = 10 - num_results |
| 1069 else: | 1087 else: |
| 1070 reruns = 2 | 1088 reruns = 2 |
| 1071 run = runner.RunTestSequence(revision_num=str(revision_number), | 1089 run = runner.RunTestSequence(revision_num=str(revision_number), |
| 1072 num_reruns=reruns) | 1090 num_reruns=reruns) |
| 1073 if num_results >= 10 or run == 0 and num_results + reruns >= 10: | 1091 if num_results >= 10 or run == 0 and num_results + reruns >= 10: |
| 1074 results_set = UpdateSetOfDoneCls(revision_number) | 1092 results_set = UpdateSetOfDoneCls(revision_number) |
| 1075 elif run != 0: | 1093 elif run != 0: |
| 1076 return False | 1094 return False |
| 1077 return True | 1095 return True |
| 1078 | 1096 |
| 1079 if random.choice([True, False]): | 1097 # Try to get up to 10 runs of each CL, starting with the most recent |
| 1080 # Select a random CL number, with greater likelihood of selecting a CL in | 1098 # CL that does not yet have 10 runs. But only perform a set of extra |
| 1081 # the more recent history than the distant past (using a simplified weighted | 1099 # runs at most 2 at a time before checking to see if new code has been |
| 1082 # bucket algorithm). If that CL has less than 10 runs, run additional. If it | 1100 # checked in. |
| 1083 # already has 10 runs, look for another CL number that is not yet have all | 1101 while revision_num > EARLIEST_REVISION and not has_run_extra: |
| 1084 # of its additional runs (do this up to 15 times). | 1102 if revision_num not in results_set: |
| 1085 tries = 0 | 1103 has_run_extra = TryToRunAdditional(revision_num) |
| 1086 # Select which "thousands bucket" we're going to run additional tests for. | 1104 revision_num -= 1 |
| 1087 bucket_size = 1000 | |
| 1088 thousands_list = range(EARLIEST_REVISION/bucket_size, | |
| 1089 int(revision_num)/bucket_size + 1) | |
| 1090 weighted_total = sum(thousands_list) | |
| 1091 generated_random_number = random.randint(0, weighted_total - 1) | |
| 1092 for i in list(reversed(thousands_list)): | |
| 1093 thousands = i | |
| 1094 weighted_total -= i | |
| 1095 if weighted_total <= generated_random_number: | |
| 1096 break | |
| 1097 while tries < 15 and not has_run_extra: | |
| 1098 # Now select a particular revision in that bucket. | |
| 1099 if thousands == int(revision_num)/bucket_size: | |
| 1100 max_range = 1 + revision_num % bucket_size | |
| 1101 else: | |
| 1102 max_range = bucket_size | |
| 1103 rev = thousands * bucket_size + random.randrange(0, max_range) | |
| 1104 if rev not in results_set: | |
| 1105 has_run_extra = TryToRunAdditional(rev) | |
| 1106 tries += 1 | |
| 1107 | |
| 1108 if not has_run_extra: | |
| 1109 # Try to get up to 10 runs of each CL, starting with the most recent | |
| 1110 # CL that does not yet have 10 runs. But only perform a set of extra | |
| 1111 # runs at most 2 at a time before checking to see if new code has been | |
| 1112 # checked in. | |
| 1113 while revision_num > EARLIEST_REVISION and not has_run_extra: | |
| 1114 if revision_num not in results_set: | |
| 1115 has_run_extra = TryToRunAdditional(revision_num) | |
| 1116 revision_num -= 1 | |
| 1117 if not has_run_extra: | 1105 if not has_run_extra: |
| 1118 # No more extra back-runs to do (for now). Wait for new code. | 1106 # No more extra back-runs to do (for now). Wait for new code. |
| 1119 time.sleep(200) | 1107 time.sleep(200) |
| 1120 return results_set | 1108 return results_set |
| 1121 | 1109 |
| 1122 | 1110 |
| 1123 def main(): | 1111 def main(): |
| 1124 runner = TestRunner() | 1112 runner = TestRunner() |
| 1125 continuous = runner.ParseArgs() | 1113 continuous = runner.ParseArgs() |
| 1126 | 1114 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1141 else: | 1129 else: |
| 1142 if runner.backfill: | 1130 if runner.backfill: |
| 1143 results_set = FillInBackHistory(results_set, runner) | 1131 results_set = FillInBackHistory(results_set, runner) |
| 1144 else: | 1132 else: |
| 1145 time.sleep(200) | 1133 time.sleep(200) |
| 1146 else: | 1134 else: |
| 1147 runner.RunTestSequence() | 1135 runner.RunTestSequence() |
| 1148 | 1136 |
| 1149 if __name__ == '__main__': | 1137 if __name__ == '__main__': |
| 1150 main() | 1138 main() |
| OLD | NEW |