| 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 # How far back in time we want to test. | 29 # How far back in time we want to test. |
| 30 EARLIEST_REVISION = 6285 | 30 EARLIEST_REVISION = 33076 |
| 31 FIRST_CHROMEDRIVER = 7823 | |
| 32 sys.path.append(TOOLS_PATH) | 31 sys.path.append(TOOLS_PATH) |
| 33 sys.path.append(os.path.join(TOP_LEVEL_DIR, 'internal', 'tests')) | 32 sys.path.append(os.path.join(TOP_LEVEL_DIR, 'internal', 'tests')) |
| 34 import post_results | 33 import post_results |
| 35 import utils | 34 import utils |
| 36 | 35 |
| 37 """This script runs to track performance and size progress of | 36 """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 | 37 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.""" | 38 the server, and will sync and run the performance tests if so.""" |
| 40 class TestRunner(object): | 39 class TestRunner(object): |
| 41 | 40 |
| (...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 browsers += ['dartium'] | 619 browsers += ['dartium'] |
| 621 has_shell = False | 620 has_shell = False |
| 622 if platform.system() == 'Darwin': | 621 if platform.system() == 'Darwin': |
| 623 browsers += ['safari'] | 622 browsers += ['safari'] |
| 624 if platform.system() == 'Windows': | 623 if platform.system() == 'Windows': |
| 625 browsers += ['ie'] | 624 browsers += ['ie'] |
| 626 has_shell = True | 625 has_shell = True |
| 627 return browsers | 626 return browsers |
| 628 | 627 |
| 629 | 628 |
| 630 class CommonBrowserTest(RuntimePerformanceTest): | |
| 631 """Runs this basic performance tests (Benchpress, some V8 benchmarks) in the | |
| 632 browser.""" | |
| 633 | |
| 634 def __init__(self, test_runner): | |
| 635 """Args: | |
| 636 test_runner: Reference to the object that notifies us when to run.""" | |
| 637 super(CommonBrowserTest, self).__init__( | |
| 638 self.Name(), BrowserTester.GetBrowsers(False), | |
| 639 'browser', ['js', 'dart2js'], | |
| 640 self.GetStandaloneBenchmarks(), test_runner, | |
| 641 self.CommonBrowserTester(self), | |
| 642 self.CommonBrowserFileProcessor(self)) | |
| 643 | |
| 644 @staticmethod | |
| 645 def Name(): | |
| 646 return 'browser-perf' | |
| 647 | |
| 648 @staticmethod | |
| 649 def GetStandaloneBenchmarks(): | |
| 650 return ['Mandelbrot', 'DeltaBlue', 'Richards', 'NBody', 'BinaryTrees', | |
| 651 'Fannkuch', 'Meteor', 'BubbleSort', 'Fibonacci', 'Loop', 'Permute', | |
| 652 'Queens', 'QuickSort', 'Recurse', 'Sieve', 'Sum', 'Tak', 'Takl', 'Towers', | |
| 653 'TreeSort'] | |
| 654 | |
| 655 class CommonBrowserTester(BrowserTester): | |
| 656 def RunTests(self): | |
| 657 """Run a performance test in the browser.""" | |
| 658 os.chdir(DART_REPO_LOC) | |
| 659 self.test.test_runner.RunCmd([ | |
| 660 'python', os.path.join('internal', 'browserBenchmarks', | |
| 661 'make_web_benchmarks.py')]) | |
| 662 | |
| 663 for browser in self.test.platform_list: | |
| 664 for version in self.test.versions: | |
| 665 if not self.test.IsValidCombination(browser, version): | |
| 666 continue | |
| 667 self.test.trace_file = os.path.join(TOP_LEVEL_DIR, | |
| 668 'tools', 'testing', 'perf_testing', self.test.result_folder_name, | |
| 669 'perf-%s-%s-%s' % (self.test.cur_time, browser, version)) | |
| 670 self.AddSvnRevisionToTrace(self.test.trace_file, browser) | |
| 671 file_path = os.path.join( | |
| 672 os.getcwd(), 'internal', 'browserBenchmarks', 'V8vDart', | |
| 673 'V8vDart_page_%s.html' % version) | |
| 674 self.test.test_runner.RunCmd( | |
| 675 ['python', os.path.join('tools', 'testing', 'run_selenium.py'), | |
| 676 '--out', '"file:///%s"' % file_path, '--browser', browser, | |
| 677 '--timeout', '600', '--mode', 'perf'], self.test.trace_file, | |
| 678 append=True) | |
| 679 | |
| 680 class CommonBrowserFileProcessor(Processor): | |
| 681 | |
| 682 def ProcessFile(self, afile, should_post_file): | |
| 683 """Comb through the html to find the performance results. | |
| 684 Returns: True if we successfully posted our data to storage and/or we can | |
| 685 delete the trace file.""" | |
| 686 os.chdir(os.path.join(TOP_LEVEL_DIR, 'tools', | |
| 687 'testing', 'perf_testing')) | |
| 688 parts = afile.split('-') | |
| 689 browser = parts[2] | |
| 690 version = parts[3] | |
| 691 f = self.OpenTraceFile(afile, should_post_file) | |
| 692 lines = f.readlines() | |
| 693 line = '' | |
| 694 i = 0 | |
| 695 revision_num = 0 | |
| 696 while '<div id="results">' not in line and i < len(lines): | |
| 697 if 'Revision' in line: | |
| 698 revision_num = int(line.split()[1].strip('"')) | |
| 699 line = lines[i] | |
| 700 i += 1 | |
| 701 | |
| 702 if i >= len(lines) or revision_num == 0: | |
| 703 # Then this run did not complete. Ignore this tracefile. | |
| 704 return True | |
| 705 | |
| 706 line = lines[i] | |
| 707 i += 1 | |
| 708 results = [] | |
| 709 if line.find('<br>') > -1: | |
| 710 results = line.split('<br>') | |
| 711 else: | |
| 712 results = line.split('<br />') | |
| 713 if results == []: | |
| 714 return True | |
| 715 upload_success = True | |
| 716 for result in results: | |
| 717 name_and_score = result.split(':') | |
| 718 if len(name_and_score) < 2: | |
| 719 break | |
| 720 name = name_and_score[0].strip() | |
| 721 score = name_and_score[1].strip() | |
| 722 if version == 'js' or version == 'v8': | |
| 723 version = 'js' | |
| 724 bench_dict = self.test.values_dict[browser][version] | |
| 725 bench_dict[name] += [float(score)] | |
| 726 self.test.revision_dict[browser][version][name] += [revision_num] | |
| 727 if not self.test.test_runner.no_upload and should_post_file: | |
| 728 upload_success = upload_success and self.ReportResults( | |
| 729 name, score, browser, version, revision_num, | |
| 730 self.GetScoreType(name)) | |
| 731 else: | |
| 732 upload_success = False | |
| 733 | |
| 734 f.close() | |
| 735 self.CalculateGeometricMean(browser, version, revision_num) | |
| 736 return upload_success | |
| 737 | |
| 738 | |
| 739 class DromaeoTester(Tester): | 629 class DromaeoTester(Tester): |
| 740 DROMAEO_BENCHMARKS = { | 630 DROMAEO_BENCHMARKS = { |
| 741 'attr': ('attributes', [ | 631 'attr': ('attributes', [ |
| 742 'getAttribute', | 632 'getAttribute', |
| 743 'element.property', | 633 'element.property', |
| 744 'setAttribute', | 634 'setAttribute', |
| 745 'element.property = value']), | 635 'element.property = value']), |
| 746 'modify': ('modify', [ | 636 'modify': ('modify', [ |
| 747 'createElement', | 637 'createElement', |
| 748 'createTextNode', | 638 'createTextNode', |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 816 DromaeoTester.GetDromaeoVersions(), | 706 DromaeoTester.GetDromaeoVersions(), |
| 817 DromaeoTester.GetDromaeoBenchmarks(), test_runner, | 707 DromaeoTester.GetDromaeoBenchmarks(), test_runner, |
| 818 self.DromaeoPerfTester(self), | 708 self.DromaeoPerfTester(self), |
| 819 self.DromaeoFileProcessor(self)) | 709 self.DromaeoFileProcessor(self)) |
| 820 | 710 |
| 821 @staticmethod | 711 @staticmethod |
| 822 def Name(): | 712 def Name(): |
| 823 return 'dromaeo' | 713 return 'dromaeo' |
| 824 | 714 |
| 825 class DromaeoPerfTester(DromaeoTester): | 715 class DromaeoPerfTester(DromaeoTester): |
| 826 def MoveChromeDriverIfNeeded(self, browser): | |
| 827 """Move the appropriate version of ChromeDriver onto the path. | |
| 828 TODO(efortuna): This is a total hack because the latest version of Chrome | |
| 829 (Dartium builds) requires a different version of ChromeDriver, that is | |
| 830 incompatible with the release or beta Chrome and vice versa. Remove these | |
| 831 shenanigans once we're back to both versions of Chrome using the same | |
| 832 version of ChromeDriver. IMPORTANT NOTE: This assumes your chromedriver is | |
| 833 in the default location (inside depot_tools). | |
| 834 | |
| 835 Returns: True if we were successfully able to download a new version of | |
| 836 chromedriver and/or move the correct chromedriver into position. | |
| 837 """ | |
| 838 current_dir = os.getcwd() | |
| 839 self.test.test_runner.GetArchive('chromedriver') | |
| 840 path = os.environ['PATH'].split(os.pathsep) | |
| 841 orig_chromedriver_path = os.path.join(DART_REPO_LOC, 'tools', 'testing', | |
| 842 'orig-chromedriver') | |
| 843 dartium_chromedriver_path = os.path.join(DART_REPO_LOC, 'tools', | |
| 844 'testing', | |
| 845 'dartium-chromedriver') | |
| 846 extension = '' | |
| 847 if platform.system() == 'Windows': | |
| 848 extension = '.exe' | |
| 849 | |
| 850 def MoveChromedriver(depot_tools, copy_to_depot_tools_dir=True, | |
| 851 from_path=None): | |
| 852 if from_path: | |
| 853 from_dir = from_path + extension | |
| 854 else: | |
| 855 from_dir = os.path.join(orig_chromedriver_path, | |
| 856 'chromedriver' + extension) | |
| 857 to_dir = os.path.join(depot_tools, 'chromedriver' + extension) | |
| 858 if not copy_to_depot_tools_dir: | |
| 859 tmp = to_dir | |
| 860 to_dir = from_dir | |
| 861 from_dir = tmp | |
| 862 print >> sys.stderr, from_dir | |
| 863 print >> sys.stderr, to_dir | |
| 864 if not os.path.exists(os.path.dirname(to_dir)): | |
| 865 os.makedirs(os.path.dirname(to_dir)) | |
| 866 if not os.path.exists(os.path.dirname(from_dir)): | |
| 867 os.makedirs(os.path.dirname(from_dir)) | |
| 868 shutil.copyfile(from_dir, to_dir) | |
| 869 | |
| 870 for loc in path: | |
| 871 if 'depot_tools' in loc: | |
| 872 if browser == 'chrome': | |
| 873 if os.path.exists(orig_chromedriver_path): | |
| 874 MoveChromedriver(loc) | |
| 875 elif browser == 'dartium': | |
| 876 if (int(self.test.test_runner.current_revision_num) < | |
| 877 FIRST_CHROMEDRIVER): | |
| 878 # If we don't have a stashed different chromedriver just use | |
| 879 # the regular chromedriver. | |
| 880 if not os.path.exists(os.path.dirname(orig_chromedriver_path)): | |
| 881 os.makedirs(os.path.dirname(orig_chromedriver_path)) | |
| 882 self.test.test_runner.RunCmd([os.path.join( | |
| 883 TOP_LEVEL_DIR, 'tools', 'testing', 'webdriver_test_setup.py'), | |
| 884 '-f', '-p', '-s']) | |
| 885 elif not os.path.exists(dartium_chromedriver_path): | |
| 886 success, _, _ = self.test.test_runner.GetArchive('chromedriver') | |
| 887 if not success: | |
| 888 return False | |
| 889 # Move original chromedriver for storage. | |
| 890 if not os.path.exists(orig_chromedriver_path): | |
| 891 MoveChromedriver(loc, copy_to_depot_tools_dir=False) | |
| 892 if self.test.test_runner.current_revision_num >= FIRST_CHROMEDRIVER: | |
| 893 # Copy Dartium chromedriver into depot_tools | |
| 894 MoveChromedriver(loc, from_path=os.path.join( | |
| 895 dartium_chromedriver_path, 'chromedriver')) | |
| 896 os.chdir(current_dir) | |
| 897 return True | |
| 898 | |
| 899 def RunTests(self): | 716 def RunTests(self): |
| 900 """Run dromaeo in the browser.""" | 717 """Run dromaeo in the browser.""" |
| 901 success, _, _ = self.test.test_runner.GetArchive('dartium') | 718 success, _, _ = self.test.test_runner.GetArchive('dartium') |
| 902 if not success: | 719 if not success: |
| 903 # Unable to download dartium. Try later. | 720 # Unable to download dartium. Try later. |
| 904 return | 721 return |
| 905 | 722 |
| 906 # Build tests. | 723 # Build tests. |
| 907 dromaeo_path = os.path.join('samples', 'third_party', 'dromaeo') | 724 dromaeo_path = os.path.join('samples', 'third_party', 'dromaeo') |
| 908 current_path = os.getcwd() | 725 current_path = os.getcwd() |
| 909 os.chdir(dromaeo_path) | 726 os.chdir(dromaeo_path) |
| 910 if os.path.exists('generate_dart2js_tests.py'): | 727 stdout, _ = self.test.test_runner.RunCmd( |
| 911 stdout, _ = self.test.test_runner.RunCmd( | 728 ['python', 'generate_perf_and_dart2js_tests.py']) |
| 912 ['python', 'generate_dart2js_tests.py']) | |
| 913 else: | |
| 914 stdout, _ = self.test.test_runner.RunCmd( | |
| 915 ['python', 'generate_frog_tests.py']) | |
| 916 os.chdir(current_path) | 729 os.chdir(current_path) |
| 917 if 'Error: Compilation failed' in stdout: | 730 if 'Error: Compilation failed' in stdout: |
| 918 return | 731 return |
| 919 versions = DromaeoTester.GetDromaeoVersions() | 732 versions = DromaeoTester.GetDromaeoVersions() |
| 920 | 733 |
| 921 for browser in BrowserTester.GetBrowsers(): | 734 for browser in BrowserTester.GetBrowsers(): |
| 922 success = self.MoveChromeDriverIfNeeded(browser) | |
| 923 if not success: | |
| 924 return | |
| 925 for version_name in versions: | 735 for version_name in versions: |
| 926 if not self.test.IsValidCombination(browser, version_name): | 736 if not self.test.IsValidCombination(browser, version_name): |
| 927 continue | 737 continue |
| 928 version = DromaeoTest.DromaeoPerfTester.GetDromaeoUrlQuery( | 738 version = DromaeoTest.DromaeoPerfTester.GetDromaeoUrlQuery( |
| 929 browser, version_name) | 739 browser, version_name) |
| 930 self.test.trace_file = os.path.join(TOP_LEVEL_DIR, | 740 self.test.trace_file = os.path.join(TOP_LEVEL_DIR, |
| 931 'tools', 'testing', 'perf_testing', self.test.result_folder_name, | 741 'tools', 'testing', 'perf_testing', self.test.result_folder_name, |
| 932 'dromaeo-%s-%s-%s' % (self.test.cur_time, browser, version_name)) | 742 'dromaeo-%s-%s-%s' % (self.test.cur_time, browser, version_name)) |
| 933 self.AddSvnRevisionToTrace(self.test.trace_file, browser) | 743 self.AddSvnRevisionToTrace(self.test.trace_file, browser) |
| 934 file_path = os.path.join(os.getcwd(), dromaeo_path, | 744 url_path = '/'.join(['/root_dart', dromaeo_path, 'index%s.html?%s'% ( |
| 935 'index%s.html?%s' % ( | 745 '-dart' if version_name == 'dart_html' else '-js', |
| 936 '' if version_name == 'dart_html' else '-js', version)) | 746 version)]) |
| 747 |
| 748 # TODO(efortuna): Make this a separate function. We should do this |
| 749 # once per cycle. |
| 750 os.chdir(os.path.join(DART_REPO_LOC, 'tools', 'testing', 'dart', |
| 751 'browser_perf_testing')) |
| 752 self.test.test_runner.RunCmd([os.path.join(DART_REPO_LOC, |
| 753 utils.GetBuildRoot(utils.GuessOS(), 'release', 'ia32'), |
| 754 'dart-sdk', 'bin', 'pub'), 'install']) |
| 755 os.chdir(current_path) |
| 756 |
| 937 self.test.test_runner.RunCmd( | 757 self.test.test_runner.RunCmd( |
| 938 ['python', os.path.join('tools', 'testing', 'run_selenium.py'), | 758 [os.path.join(utils.GetBuildRoot( |
| 939 '--out', '"file:///%s"' % file_path, '--browser', browser, | 759 utils.GuessOS(), 'release', 'ia32'), 'dart-sdk', 'bin', 'dart'), |
| 940 '--timeout', '900', '--mode', 'dromaeo'], self.test.trace_file, | 760 '--package-root=%s' % os.path.join(DART_REPO_LOC, 'tools', |
| 761 'testing', 'dart', 'browser_perf_testing', 'packages'), |
| 762 os.path.join('tools', 'testing', 'dart', 'browser_perf_testing', |
| 763 'lib', 'browser_perf_testing.dart'), |
| 764 '--browser', browser, '--termination_test_file', |
| 765 '/root_dart/samples/third_party/dromaeo/dromaeo_end_condition.' |
| 766 'js', '--test_path', url_path], self.test.trace_file, |
| 941 append=True) | 767 append=True) |
| 942 # Put default Chromedriver back in. | |
| 943 self.MoveChromeDriverIfNeeded('chrome') | |
| 944 | 768 |
| 945 @staticmethod | 769 @staticmethod |
| 946 def GetDromaeoUrlQuery(browser, version): | 770 def GetDromaeoUrlQuery(browser, version): |
| 947 if browser == 'dartium': | |
| 948 version = version.replace('frog', 'dart') | |
| 949 version = version.replace('_','AND') | 771 version = version.replace('_','AND') |
| 950 tags = DromaeoTester.GetValidDromaeoTags() | 772 tags = DromaeoTester.GetValidDromaeoTags() |
| 951 return 'OR'.join([ '%sAND%s' % (version, tag) for tag in tags]) | 773 return 'OR'.join([ '%sAND%s' % (version, tag) for tag in tags]) |
| 952 | 774 |
| 953 | 775 |
| 954 class DromaeoFileProcessor(Processor): | 776 class DromaeoFileProcessor(Processor): |
| 955 def ProcessFile(self, afile, should_post_file): | 777 def ProcessFile(self, afile, should_post_file): |
| 956 """Comb through the html to find the performance results. | 778 """Comb through the html to find the performance results. |
| 957 Returns: True if we successfully posted our data to storage.""" | 779 Returns: True if we successfully posted our data to storage.""" |
| 958 parts = afile.split('-') | 780 parts = afile.split('-') |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 else: | 817 else: |
| 996 upload_success = False | 818 upload_success = False |
| 997 | 819 |
| 998 f.close() | 820 f.close() |
| 999 self.CalculateGeometricMean(browser, version, revision_num) | 821 self.CalculateGeometricMean(browser, version, revision_num) |
| 1000 return upload_success | 822 return upload_success |
| 1001 | 823 |
| 1002 class TestBuilder(object): | 824 class TestBuilder(object): |
| 1003 """Construct the desired test object.""" | 825 """Construct the desired test object.""" |
| 1004 available_suites = dict((suite.Name(), suite) for suite in [ | 826 available_suites = dict((suite.Name(), suite) for suite in [ |
| 1005 CommonBrowserTest, DromaeoTest]) | 827 DromaeoTest]) |
| 1006 | 828 |
| 1007 @staticmethod | 829 @staticmethod |
| 1008 def MakeTest(test_name, test_runner): | 830 def MakeTest(test_name, test_runner): |
| 1009 return TestBuilder.available_suites[test_name](test_runner) | 831 return TestBuilder.available_suites[test_name](test_runner) |
| 1010 | 832 |
| 1011 @staticmethod | 833 @staticmethod |
| 1012 def AvailableSuiteNames(): | 834 def AvailableSuiteNames(): |
| 1013 return TestBuilder.available_suites.keys() | 835 return TestBuilder.available_suites.keys() |
| 1014 | 836 |
| 1015 | 837 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1131 else: | 953 else: |
| 1132 if runner.backfill: | 954 if runner.backfill: |
| 1133 results_set = FillInBackHistory(results_set, runner) | 955 results_set = FillInBackHistory(results_set, runner) |
| 1134 else: | 956 else: |
| 1135 time.sleep(200) | 957 time.sleep(200) |
| 1136 else: | 958 else: |
| 1137 runner.RunTestSequence() | 959 runner.RunTestSequence() |
| 1138 | 960 |
| 1139 if __name__ == '__main__': | 961 if __name__ == '__main__': |
| 1140 main() | 962 main() |
| OLD | NEW |