Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 3 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 4 # for details. All rights reserved. Use of this source code is governed by a | 4 # for details. All rights reserved. Use of this source code is governed by a |
| 5 # BSD-style license that can be found in the LICENSE file. | 5 # BSD-style license that can be found in the LICENSE file. |
| 6 | 6 |
| 7 import datetime | 7 import datetime |
| 8 import getpass | 8 import getpass |
| 9 import math | 9 import math |
| 10 try: | 10 try: |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 334 self.values_dict[platform] = dict() | 334 self.values_dict[platform] = dict() |
| 335 for f in variants: | 335 for f in variants: |
| 336 self.revision_dict[platform][f] = dict() | 336 self.revision_dict[platform][f] = dict() |
| 337 self.values_dict[platform][f] = dict() | 337 self.values_dict[platform][f] = dict() |
| 338 for val in values_list: | 338 for val in values_list: |
| 339 self.revision_dict[platform][f][val] = [] | 339 self.revision_dict[platform][f][val] = [] |
| 340 self.values_dict[platform][f][val] = [] | 340 self.values_dict[platform][f][val] = [] |
| 341 for extra_metric in extra_metrics: | 341 for extra_metric in extra_metrics: |
| 342 self.revision_dict[platform][f][extra_metric] = [] | 342 self.revision_dict[platform][f][extra_metric] = [] |
| 343 self.values_dict[platform][f][extra_metric] = [] | 343 self.values_dict[platform][f][extra_metric] = [] |
| 344 | 344 |
| 345 def is_valid_combination(self, platform, variant): | |
| 346 """Check whether data should be captured for this platform/variant | |
| 347 combination. | |
| 348 """ | |
| 349 return True | |
| 350 | |
| 345 def run(self, graph_only): | 351 def run(self, graph_only): |
| 346 """Run the benchmarks/tests from the command line and plot the | 352 """Run the benchmarks/tests from the command line and plot the |
| 347 results. | 353 results. |
| 348 | 354 |
| 349 Args: | 355 Args: |
| 350 graph_only: True if we should just graph the results instead of also | 356 graph_only: True if we should just graph the results instead of also |
| 351 running tests.""" | 357 running tests.""" |
| 352 for visitor in [self.tester, self.file_processor, self.grapher]: | 358 for visitor in [self.tester, self.file_processor, self.grapher]: |
| 353 visitor.prepare() | 359 visitor.prepare() |
| 354 | 360 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 377 methods that many Tester objects use. Any class that would like to be a | 383 methods that many Tester objects use. Any class that would like to be a |
| 378 TesterVisitor must implement the run_tests() method.""" | 384 TesterVisitor must implement the run_tests() method.""" |
| 379 | 385 |
| 380 def __init__(self, test): | 386 def __init__(self, test): |
| 381 self.test = test | 387 self.test = test |
| 382 | 388 |
| 383 def prepare(self): | 389 def prepare(self): |
| 384 """Perform any initial setup required before the test is run.""" | 390 """Perform any initial setup required before the test is run.""" |
| 385 pass | 391 pass |
| 386 | 392 |
| 387 def add_svn_revision_to_trace(self, outfile): | 393 def add_svn_revision_to_trace(self, outfile, browser = None): |
| 388 """Add the svn version number to the provided tracefile.""" | 394 """Add the svn version number to the provided tracefile.""" |
| 389 def search_for_revision(svn_info_command): | 395 def search_for_revision(svn_info_command): |
| 390 p = subprocess.Popen(svn_info_command, stdout = subprocess.PIPE, | 396 p = subprocess.Popen(svn_info_command, stdout = subprocess.PIPE, |
| 391 stderr = subprocess.STDOUT, shell = | 397 stderr = subprocess.STDOUT, shell = |
| 392 self.test.test_runner.has_shell) | 398 self.test.test_runner.has_shell) |
| 393 output, _ = p.communicate() | 399 output, _ = p.communicate() |
| 394 for line in output.split('\n'): | 400 for line in output.split('\n'): |
| 395 if 'Revision' in line: | 401 if 'Revision' in line: |
| 396 self.test.test_runner.run_cmd(['echo', line.strip()], outfile) | 402 self.test.test_runner.run_cmd(['echo', line.strip()], outfile) |
| 397 return True | 403 return True |
| 398 return False | 404 return False |
| 399 | 405 |
| 400 if not search_for_revision(['svn', 'info']): | 406 def get_dartium_revision(): |
| 407 version_file_name = os.path.join(DART_INSTALL_LOCATION, 'client', 'tests', | |
| 408 'dartium', 'LAST_VERSION') | |
| 409 version_file = open(version_file_name, 'r') | |
| 410 version = version_file.read().split('.')[-2] | |
| 411 version_file.close() | |
| 412 return version | |
| 413 | |
| 414 if browser and browser == 'dartium': | |
| 415 revision = get_dartium_revision() | |
| 416 self.test.test_runner.run_cmd(['echo', 'Revision: ' + revision], outfile) | |
| 417 elif not search_for_revision(['svn', 'info']): | |
| 401 if not search_for_revision(['git', 'svn', 'info']): | 418 if not search_for_revision(['git', 'svn', 'info']): |
| 402 self.test.test_runner.run_cmd(['echo', 'Revision: unknown'], outfile) | 419 self.test.test_runner.run_cmd(['echo', 'Revision: unknown'], outfile) |
| 403 | 420 |
| 404 | 421 |
| 405 class Processor(object): | 422 class Processor(object): |
| 406 """The base level vistor class that processes tests. It contains convenience | 423 """The base level vistor class that processes tests. It contains convenience |
| 407 methods that many File Processor objects use. Any class that would like to be | 424 methods that many File Processor objects use. Any class that would like to be |
| 408 a ProcessorVisitor must implement the process_file() method.""" | 425 a ProcessorVisitor must implement the process_file() method.""" |
| 409 | 426 |
| 410 def __init__(self, test): | 427 def __init__(self, test): |
| 411 self.test = test | 428 self.test = test |
| 412 | 429 |
| 413 def prepare(self): | 430 def prepare(self): |
| 414 """Perform any initial setup required before the test is run.""" | 431 """Perform any initial setup required before the test is run.""" |
| 415 pass | 432 pass |
| 416 | 433 |
| 417 def calculate_geometric_mean(self, platform, variant, svn_revision): | 434 def calculate_geometric_mean(self, platform, variant, svn_revision): |
| 418 """Calculate the aggregate geometric mean for JS and frog benchmark sets, | 435 """Calculate the aggregate geometric mean for JS and frog benchmark sets, |
| 419 given two benchmark dictionaries.""" | 436 given two benchmark dictionaries.""" |
| 420 geo_mean = 0 | 437 geo_mean = 0 |
| 421 for benchmark in self.test.values_list: | 438 # TODO(vsm): Suppress graphing this combination altogether. For |
| 422 geo_mean += math.log(self.test.values_dict[platform][variant][benchmark][ | 439 # now, we feed a geomean of 0. |
| 423 len(self.test.values_dict[platform][variant][benchmark]) - 1]) | 440 if self.test.is_valid_combination(platform, variant): |
| 441 for benchmark in self.test.values_list: | |
| 442 geo_mean += math.log(self.test.values_dict[platform][variant][benchmark] [ | |
|
Emily Fortuna
2012/04/17 19:59:29
80 char.
vsm
2012/04/18 15:46:54
Done.
| |
| 443 len(self.test.values_dict[platform][variant][benchmark]) - 1]) | |
| 424 | 444 |
| 425 self.test.values_dict[platform][variant]['Geo-Mean'] += \ | 445 self.test.values_dict[platform][variant]['Geo-Mean'] += \ |
| 426 [math.pow(math.e, geo_mean / len(self.test.values_list))] | 446 [math.pow(math.e, geo_mean / len(self.test.values_list))] |
| 427 self.test.revision_dict[platform][variant]['Geo-Mean'] += [svn_revision] | 447 self.test.revision_dict[platform][variant]['Geo-Mean'] += [svn_revision] |
| 428 | 448 |
| 429 | 449 |
| 430 class Grapher(object): | 450 class Grapher(object): |
| 431 """The base level visitor class that generates graphs for data. It contains | 451 """The base level visitor class that generates graphs for data. It contains |
| 432 convenience methods that many Grapher objects use. Any class that would like | 452 convenience methods that many Grapher objects use. Any class that would like |
| 433 to be a GrapherVisitor must implement the plot_results() method.""" | 453 to be a GrapherVisitor must implement the plot_results() method.""" |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 557 def plot_avg_perf(self, png_filename): | 577 def plot_avg_perf(self, png_filename): |
| 558 """Generate a plot that shows the performance changes of the geomentric | 578 """Generate a plot that shows the performance changes of the geomentric |
| 559 mean of JS and frog benchmark performance over svn history.""" | 579 mean of JS and frog benchmark performance over svn history.""" |
| 560 (title, y_axis, size_x, size_y, loc, filename) = \ | 580 (title, y_axis, size_x, size_y, loc, filename) = \ |
| 561 ('Geometric Mean of benchmark %s performance on %s ' % | 581 ('Geometric Mean of benchmark %s performance on %s ' % |
| 562 (self.test.platform_type, utils.GuessOS()), 'Speed (bigger = better)', | 582 (self.test.platform_type, utils.GuessOS()), 'Speed (bigger = better)', |
| 563 16, 5, 'lower left', 'avg'+png_filename) | 583 16, 5, 'lower left', 'avg'+png_filename) |
| 564 clear_axis = True | 584 clear_axis = True |
| 565 for platform in self.test.platform_list: | 585 for platform in self.test.platform_list: |
| 566 for version in self.test.versions: | 586 for version in self.test.versions: |
| 567 for metric in self.test.extra_metrics: | 587 if self.test.is_valid_combination(platform, version): |
| 568 self.style_and_save_perf_plot(title, y_axis, size_x, size_y, loc, | 588 for metric in self.test.extra_metrics: |
| 569 filename, [platform], [version], | 589 self.style_and_save_perf_plot(title, y_axis, size_x, size_y, loc, |
| 570 [metric], clear_axis) | 590 filename, [platform], [version], |
| 591 [metric], clear_axis) | |
| 571 clear_axis = False | 592 clear_axis = False |
|
Emily Fortuna
2012/04/17 19:59:29
This line also needs to be indented two more space
vsm
2012/04/18 15:46:54
Thanks for the catch!
On 2012/04/17 19:59:29, Emi
| |
| 572 | 593 |
| 573 def plot_results(self, png_filename): | 594 def plot_results(self, png_filename): |
| 574 self.plot_all_perf(png_filename) | 595 self.plot_all_perf(png_filename) |
| 575 self.plot_avg_perf('2' + png_filename) | 596 self.plot_avg_perf('2' + png_filename) |
| 576 | 597 |
| 577 | 598 |
| 578 class CommonCommandLineTest(RuntimePerformanceTest): | 599 class CommonCommandLineTest(RuntimePerformanceTest): |
| 579 """Run the basic performance tests (Benchpress, some V8 benchmarks) from the | 600 """Run the basic performance tests (Benchpress, some V8 benchmarks) from the |
| 580 command line.""" | 601 command line.""" |
| 581 | 602 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 647 [revision_num] | 668 [revision_num] |
| 648 self.test.values_dict['commandline']['frog'][benchmark] += \ | 669 self.test.values_dict['commandline']['frog'][benchmark] += \ |
| 649 [frog_value] | 670 [frog_value] |
| 650 f.close() | 671 f.close() |
| 651 | 672 |
| 652 self.calculate_geometric_mean('commandline', 'frog', revision_num) | 673 self.calculate_geometric_mean('commandline', 'frog', revision_num) |
| 653 self.calculate_geometric_mean('commandline', 'js', revision_num) | 674 self.calculate_geometric_mean('commandline', 'js', revision_num) |
| 654 | 675 |
| 655 | 676 |
| 656 class BrowserTester(Tester): | 677 class BrowserTester(Tester): |
| 657 # TODO(vsm): Add Dartium. | |
| 658 @staticmethod | 678 @staticmethod |
| 659 def get_browsers(): | 679 def get_browsers(): |
| 660 browsers = ['ff', 'chrome'] | 680 browsers = ['dartium', 'ff', 'chrome'] |
| 681 has_shell = False | |
| 661 if platform.system() == 'Darwin': | 682 if platform.system() == 'Darwin': |
| 662 browsers += ['safari'] | 683 browsers += ['safari'] |
| 663 if platform.system() == 'Windows': | 684 if platform.system() == 'Windows': |
| 664 browsers += ['ie'] | 685 browsers += ['ie'] |
| 686 has_shell = True | |
| 687 if 'dartium' in browsers: | |
| 688 # Fetch it if necessary. | |
| 689 get_dartium = ['python', | |
| 690 os.path.join(DART_INSTALL_LOCATION, 'tools', 'get_drt.py'), | |
| 691 '--dartium'] | |
| 692 # TODO(vsm): It's inconvenient that run_cmd isn't in scope here. | |
|
Emily Fortuna
2012/04/17 19:59:29
Perhaps in any "BrowserTest" just before it is act
vsm
2012/04/18 15:46:54
This does mean checking multiple times on a single
| |
| 693 # Perhaps there is a better place to put that or this. | |
| 694 subprocess.Popen(get_dartium, shell=has_shell) | |
| 665 return browsers | 695 return browsers |
| 666 | 696 |
| 667 | 697 |
| 668 class CommonBrowserTest(RuntimePerformanceTest): | 698 class CommonBrowserTest(RuntimePerformanceTest): |
| 669 """Runs this basic performance tests (Benchpress, some V8 benchmarks) in the | 699 """Runs this basic performance tests (Benchpress, some V8 benchmarks) in the |
| 670 browser.""" | 700 browser.""" |
| 671 | 701 |
| 672 def __init__(self, test_runner): | 702 def __init__(self, test_runner): |
| 673 """Args: | 703 """Args: |
| 674 test_runner: Reference to the object that notifies us when to run.""" | 704 test_runner: Reference to the object that notifies us when to run.""" |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 693 class CommonBrowserTester(BrowserTester): | 723 class CommonBrowserTester(BrowserTester): |
| 694 def run_tests(self): | 724 def run_tests(self): |
| 695 """Run a performance test in the browser.""" | 725 """Run a performance test in the browser.""" |
| 696 os.chdir('frog') | 726 os.chdir('frog') |
| 697 self.test.test_runner.run_cmd(['python', os.path.join('benchmarks', | 727 self.test.test_runner.run_cmd(['python', os.path.join('benchmarks', |
| 698 'make_web_benchmarks.py')]) | 728 'make_web_benchmarks.py')]) |
| 699 os.chdir('..') | 729 os.chdir('..') |
| 700 | 730 |
| 701 for browser in BrowserTester.get_browsers(): | 731 for browser in BrowserTester.get_browsers(): |
| 702 for version in self.test.versions: | 732 for version in self.test.versions: |
| 733 if not self.test.is_valid_combination(browser, version): | |
| 734 continue | |
| 703 self.test.trace_file = os.path.join( | 735 self.test.trace_file = os.path.join( |
| 704 'tools', 'testing', 'perf_testing', self.test.result_folder_name, | 736 'tools', 'testing', 'perf_testing', self.test.result_folder_name, |
| 705 'perf-%s-%s-%s' % (self.test.cur_time, browser, version)) | 737 'perf-%s-%s-%s' % (self.test.cur_time, browser, version)) |
| 706 self.add_svn_revision_to_trace(self.test.trace_file) | 738 self.add_svn_revision_to_trace(self.test.trace_file, browser) |
| 707 file_path = os.path.join( | 739 file_path = os.path.join( |
| 708 os.getcwd(), 'internal', 'browserBenchmarks', | 740 os.getcwd(), 'internal', 'browserBenchmarks', |
| 709 'benchmark_page_%s.html' % version) | 741 'benchmark_page_%s.html' % version) |
| 710 self.test.test_runner.run_cmd( | 742 self.test.test_runner.run_cmd( |
| 711 ['python', os.path.join('tools', 'testing', 'run_selenium.py'), | 743 ['python', os.path.join('tools', 'testing', 'run_selenium.py'), |
| 712 '--out', file_path, '--browser', browser, | 744 '--out', file_path, '--browser', browser, |
| 713 '--timeout', '600', '--mode', 'perf'], self.test.trace_file, | 745 '--timeout', '600', '--mode', 'perf'], self.test.trace_file, |
| 714 append=True) | 746 append=True) |
| 715 | 747 |
| 716 class CommonBrowserFileProcessor(Processor): | 748 class CommonBrowserFileProcessor(Processor): |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 837 self.name(), BrowserTester.get_browsers(), 'browser', | 869 self.name(), BrowserTester.get_browsers(), 'browser', |
| 838 DromaeoTester.get_dromaeo_versions(), | 870 DromaeoTester.get_dromaeo_versions(), |
| 839 DromaeoTester.get_dromaeo_benchmarks(), test_runner, | 871 DromaeoTester.get_dromaeo_benchmarks(), test_runner, |
| 840 self.DromaeoPerfTester(self), | 872 self.DromaeoPerfTester(self), |
| 841 self.DromaeoFileProcessor(self)) | 873 self.DromaeoFileProcessor(self)) |
| 842 | 874 |
| 843 @staticmethod | 875 @staticmethod |
| 844 def name(): | 876 def name(): |
| 845 return 'dromaeo' | 877 return 'dromaeo' |
| 846 | 878 |
| 879 def is_valid_combination(self, browser, version): | |
| 880 # TODO(vsm): This avoids a bug in 32-bit Chrome (dartium) | |
| 881 # running JS dromaeo. | |
| 882 if browser == 'dartium' and version == 'js': | |
| 883 return False | |
| 884 return True | |
| 885 | |
| 847 class DromaeoPerfTester(DromaeoTester): | 886 class DromaeoPerfTester(DromaeoTester): |
| 848 def run_tests(self): | 887 def run_tests(self): |
| 849 """Run dromaeo in the browser.""" | 888 """Run dromaeo in the browser.""" |
| 850 | 889 |
| 851 # Build tests. | 890 # Build tests. |
| 852 dromaeo_path = os.path.join('samples', 'third_party', 'dromaeo') | 891 dromaeo_path = os.path.join('samples', 'third_party', 'dromaeo') |
| 853 current_path = os.getcwd() | 892 current_path = os.getcwd() |
| 854 os.chdir(dromaeo_path) | 893 os.chdir(dromaeo_path) |
| 855 self.test.test_runner.run_cmd(['python', 'generate_frog_tests.py']) | 894 self.test.test_runner.run_cmd(['python', 'generate_frog_tests.py']) |
| 856 os.chdir(current_path) | 895 os.chdir(current_path) |
| 857 | 896 |
| 858 versions = DromaeoTester.get_dromaeo_versions() | 897 versions = DromaeoTester.get_dromaeo_versions() |
| 859 | 898 |
| 860 for browser in BrowserTester.get_browsers(): | 899 for browser in BrowserTester.get_browsers(): |
| 861 for version_name in versions: | 900 for version_name in versions: |
| 901 if not self.test.is_valid_combination(browser, version): | |
| 902 continue | |
| 862 version = DromaeoTest.DromaeoPerfTester.get_dromaeo_url_query( | 903 version = DromaeoTest.DromaeoPerfTester.get_dromaeo_url_query( |
| 863 version_name) | 904 browser, version_name) |
| 864 self.test.trace_file = os.path.join( | 905 self.test.trace_file = os.path.join( |
| 865 'tools', 'testing', 'perf_testing', self.test.result_folder_name, | 906 'tools', 'testing', 'perf_testing', self.test.result_folder_name, |
| 866 'dromaeo-%s-%s-%s' % (self.test.cur_time, browser, version_name)) | 907 'dromaeo-%s-%s-%s' % (self.test.cur_time, browser, version_name)) |
| 867 self.add_svn_revision_to_trace(self.test.trace_file) | 908 self.add_svn_revision_to_trace(self.test.trace_file, browser) |
| 868 file_path = os.path.join(os.getcwd(), dromaeo_path, | 909 file_path = os.path.join(os.getcwd(), dromaeo_path, |
| 869 'index-js.html?%s' % version) | 910 'index-js.html?%s' % version) |
| 870 self.test.test_runner.run_cmd( | 911 self.test.test_runner.run_cmd( |
| 871 ['python', os.path.join('tools', 'testing', 'run_selenium.py'), | 912 ['python', os.path.join('tools', 'testing', 'run_selenium.py'), |
| 872 '--out', file_path, '--browser', browser, | 913 '--out', file_path, '--browser', browser, |
| 873 '--timeout', '600', '--mode', 'dromaeo'], self.test.trace_file, | 914 '--timeout', '600', '--mode', 'dromaeo'], self.test.trace_file, |
| 874 append=True) | 915 append=True) |
| 875 | 916 |
| 876 @staticmethod | 917 @staticmethod |
| 877 def get_dromaeo_url_query(version): | 918 def get_dromaeo_url_query(browser, version): |
| 919 if browser == 'dartium': | |
| 920 version = version.replace('frog', 'dart') | |
| 878 version = version.replace('_','&') | 921 version = version.replace('_','&') |
| 879 tags = DromaeoTester.get_valid_dromaeo_tags() | 922 tags = DromaeoTester.get_valid_dromaeo_tags() |
| 880 return '|'.join([ '%s&%s' % (version, tag) for tag in tags]) | 923 return '|'.join([ '%s&%s' % (version, tag) for tag in tags]) |
| 881 | 924 |
| 882 | 925 |
| 883 class DromaeoFileProcessor(Processor): | 926 class DromaeoFileProcessor(Processor): |
| 884 def process_file(self, afile): | 927 def process_file(self, afile): |
| 885 """Comb through the html to find the performance results.""" | 928 """Comb through the html to find the performance results.""" |
| 886 parts = afile.split('-') | 929 parts = afile.split('-') |
| 887 browser = parts[2] | 930 browser = parts[2] |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1219 while True: | 1262 while True: |
| 1220 if runner.has_new_code(): | 1263 if runner.has_new_code(): |
| 1221 runner.run_test_sequence() | 1264 runner.run_test_sequence() |
| 1222 else: | 1265 else: |
| 1223 time.sleep(200) | 1266 time.sleep(200) |
| 1224 else: | 1267 else: |
| 1225 runner.run_test_sequence() | 1268 runner.run_test_sequence() |
| 1226 | 1269 |
| 1227 if __name__ == '__main__': | 1270 if __name__ == '__main__': |
| 1228 main() | 1271 main() |
| OLD | NEW |