7e8f654b1bac581b1d7638ae30a8b8bcc621525a
[WebKit-https.git] / Tools / Scripts / webkitpy / benchmark_runner / run_benchmark.py
1 #!/usr/bin/env python
2
3 import argparse
4 import json
5 import logging
6 import platform
7 import os
8 import sys
9
10 from browser_driver.browser_driver_factory import BrowserDriverFactory
11 from benchmark_runner import BenchmarkRunner
12 from webdriver_benchmark_runner import WebDriverBenchmarkRunner
13 from webserver_benchmark_runner import WebServerBenchmarkRunner
14
15
16 _log = logging.getLogger(__name__)
17 benchmark_runner_subclasses = {
18     WebDriverBenchmarkRunner.name: WebDriverBenchmarkRunner,
19     WebServerBenchmarkRunner.name: WebServerBenchmarkRunner,
20 }
21
22
23 def default_platform():
24     if sys.platform.startswith('linux'):
25         return 'linux'
26     return 'osx'
27
28
29 def default_browser():
30     if sys.platform.startswith('linux'):
31         return 'minibrowser-gtk'
32     return 'safari'
33
34
35 def parse_args():
36     parser = argparse.ArgumentParser(description='Run browser based performance benchmarks. To run a single benchmark in the recommended way, use run-benchmark --plan. To see the vailable benchmarks, use run-benchmark --list-plans.')
37     mutual_group = parser.add_mutually_exclusive_group(required=True)
38     mutual_group.add_argument('--plan', help='Run a specific benchmark plan (e.g. speedometer, jetstream).')
39     mutual_group.add_argument('--list-plans', action='store_true', help='List all available benchmark plans.')
40     mutual_group.add_argument('--allplans', action='store_true', help='Run all available benchmark plans in order.')
41     mutual_group.add_argument('--read-results-json', dest='json_file', help='Instead of running a benchmark, format the output saved in JSON_FILE.')
42     parser.add_argument('--output-file', default=None, help='Save detailed results to OUTPUT in JSON format. By default, results will not be saved.')
43     parser.add_argument('--build-directory', dest='build_dir', help='Path to the browser executable (e.g. WebKitBuild/Release/).')
44     parser.add_argument('--count', type=int, help='Number of times to run the benchmark (e.g. 5).')
45     parser.add_argument('--driver', default=WebServerBenchmarkRunner.name, choices=benchmark_runner_subclasses.keys(), help='Use the specified benchmark driver. Defaults to %s.' % WebServerBenchmarkRunner.name)
46     parser.add_argument('--browser', default=default_browser(), choices=BrowserDriverFactory.available_browsers(), help='Browser to run the nechmark in. Defaults to %s.' % default_browser())
47     parser.add_argument('--platform', default=default_platform(), choices=BrowserDriverFactory.available_platforms(), help='Platform that this script is running on. Defaults to %s.' % default_platform())
48     parser.add_argument('--local-copy', help='Path to a local copy of the benchmark (e.g. PerformanceTests/SunSpider/).')
49     parser.add_argument('--device-id', default=None, help='Undocumented option for mobile device testing.')
50     parser.add_argument('--debug', action='store_true', help='Enable debug logging.')
51     parser.add_argument('--no-adjust-unit', dest='scale_unit', action='store_false', help="Don't convert to scientific notation.")
52
53     args = parser.parse_args()
54
55     if args.debug:
56         _log.setLevel(logging.DEBUG)
57     _log.debug('Initializing program with following parameters')
58     _log.debug('\toutput file name\t: %s' % args.output_file)
59     _log.debug('\tbuild directory\t: %s' % args.build_dir)
60     _log.debug('\tplan name\t: %s', args.plan)
61
62     return args
63
64 def run_benchmark_plan(args, plan):
65     benchmark_runner_class = benchmark_runner_subclasses[args.driver]
66     runner = benchmark_runner_class(plan, args.local_copy, args.count, args.build_dir, args.output_file, args.platform, args.browser, args.scale_unit, args.device_id)
67     runner.execute()
68
69
70 def list_benchmark_plans():
71     print "Available benchmark plans: "
72     for plan in BenchmarkRunner.available_plans():
73         print "\t%s" % plan
74
75 def start(args):
76     if args.json_file:
77         results_json = json.load(open(args.json_file, 'r'))
78         if 'debugOutput' in results_json:
79             del results_json['debugOutput']
80         BenchmarkRunner.show_results(results_json, args.scale_unit)
81         return
82     if args.allplans:
83         failed = []
84         skipped = []
85         planlist = BenchmarkRunner.available_plans()
86         skippedfile = os.path.join(plandir, 'Skipped')
87         if not planlist:
88             raise Exception('Cant find any .plan file in directory %s' % BenchmarkRunner.plan_directory())
89         if os.path.isfile(skippedfile):
90             skipped = [line.strip() for line in open(skippedfile) if not line.startswith('#') and len(line) > 1]
91         for plan in sorted(planlist):
92             if plan in skipped:
93                 _log.info('Skipping benchmark plan: %s because is listed on the Skipped file' % plan)
94                 continue
95             _log.info('Starting benchmark plan: %s' % plan)
96             try:
97                 run_benchmark_plan(args, plan)
98                 _log.info('Finished benchmark plan: %s' % plan)
99             except KeyboardInterrupt:
100                 raise
101             except:
102                 failed.append(plan)
103                 _log.exception('Error running benchmark plan: %s' % plan)
104         if failed:
105             _log.error('The following benchmark plans have failed: %s' % failed)
106         return len(failed)
107     if args.list_plans:
108         list_benchmark_plans()
109         return
110
111     run_benchmark_plan(args, args.plan)
112
113
114 def format_logger(logger):
115     logger.setLevel(logging.INFO)
116     ch = logging.StreamHandler()
117     formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
118     ch.setFormatter(formatter)
119     logger.addHandler(ch)
120
121
122 def main():
123     return start(parse_args())