Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(124)

Side by Side Diff: mojo/devtools/common/mojo_benchmark

Issue 1435523002: Refactor mojo_benchmark. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/devtools/common/devtoolslib/benchmark_unittest.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2015 The Chromium Authors. All rights reserved. 2 # Copyright 2015 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Runner for Mojo application benchmarks.""" 6 """Runner for Mojo application benchmarks."""
7 7
8 import argparse 8 import argparse
9 import logging 9 import logging
10 import os.path
11 import re
12 import sys 10 import sys
13 import time 11 import time
14 12
13 from devtoolslib import benchmark
14 from devtoolslib import perf_dashboard
15 from devtoolslib import shell_arguments 15 from devtoolslib import shell_arguments
16 from devtoolslib import shell_config 16 from devtoolslib import shell_config
17 from devtoolslib import perf_dashboard
18 17
19 18
20 _DESCRIPTION = """Runner for Mojo application benchmarks. 19 _DESCRIPTION = """Runner for Mojo application benchmarks.
21 20
22 |benchmark_list_file| has to be a valid Python program that sets a |benchmarks| 21 |benchmark_list_file| has to be a valid Python program that sets a |benchmarks|
23 dictionary. For description of the required format see 22 dictionary. For description of the required format see
24 https://github.com/domokit/devtools/blob/master/docs/mojo_benchmark.md . 23 https://github.com/domokit/devtools/blob/master/docs/mojo_benchmark.md .
25 """ 24 """
26 25
27 _logger = logging.getLogger() 26 _logger = logging.getLogger()
28 27
29 _BENCHMARK_APP = 'https://core.mojoapps.io/benchmark.mojo'
30 _CACHE_SERVICE_URL = 'mojo:url_response_disk_cache' 28 _CACHE_SERVICE_URL = 'mojo:url_response_disk_cache'
31 _NETWORK_SERVICE_URL = 'mojo:network_service' 29 _NETWORK_SERVICE_URL = 'mojo:network_service'
32 30
33 _COLD_START_SHELL_ARGS = [ 31 _COLD_START_SHELL_ARGS = [
34 '--args-for=%s %s' % (_CACHE_SERVICE_URL, '--clear'), 32 '--args-for=%s %s' % (_CACHE_SERVICE_URL, '--clear'),
35 '--args-for=%s %s' % (_NETWORK_SERVICE_URL, '--clear'), 33 '--args-for=%s %s' % (_NETWORK_SERVICE_URL, '--clear'),
36 ] 34 ]
37 35
38 # Additional time in seconds allocated per shell run to accommodate start-up.
39 # The shell should terminate before hitting this time out, it is an error if it
40 # doesn't.
41 _EXTRA_TIMEOUT = 20
42
43 _MEASUREMENT_RESULT_FORMAT = r"""
44 ^ # Beginning of the line.
45 measurement: # Hard-coded tag.
46 \s+(\S+) # Match measurement spec.
47 \s+(\S+) # Match measurement result.
48 $ # End of the line.
49 """
50
51 _MEASUREMENT_REGEX = re.compile(_MEASUREMENT_RESULT_FORMAT, re.VERBOSE)
52
53 36
54 def _generate_benchmark_variants(benchmark_spec): 37 def _generate_benchmark_variants(benchmark_spec):
55 """Generates benchmark specifications for individual variants of the given 38 """Generates benchmark specifications for individual variants of the given
56 benchmark: cold start and warm start. 39 benchmark: cold start and warm start.
57 40
58 Returns: 41 Returns:
59 A list of benchmark specs corresponding to individual variants of the given 42 A list of benchmark specs corresponding to individual variants of the given
60 benchmark. 43 benchmark.
61 """ 44 """
62 variants = [] 45 variants = []
63 variants.append({ 46 variants.append({
64 'variant_name': 'cold start', 47 'variant_name': 'cold start',
65 'app': benchmark_spec['app'], 48 'app': benchmark_spec['app'],
66 'duration': benchmark_spec['duration'], 49 'duration': benchmark_spec['duration'],
67 'measurements': benchmark_spec['measurements'], 50 'measurements': benchmark_spec['measurements'],
68 'shell-args': benchmark_spec.get('shell-args', 51 'shell-args': benchmark_spec.get('shell-args',
69 []) + _COLD_START_SHELL_ARGS}) 52 []) + _COLD_START_SHELL_ARGS})
70 variants.append({ 53 variants.append({
71 'variant_name': 'warm start', 54 'variant_name': 'warm start',
72 'app': benchmark_spec['app'], 55 'app': benchmark_spec['app'],
73 'duration': benchmark_spec['duration'], 56 'duration': benchmark_spec['duration'],
74 'measurements': benchmark_spec['measurements'], 57 'measurements': benchmark_spec['measurements'],
75 'shell-args': benchmark_spec.get('shell-args', [])}) 58 'shell-args': benchmark_spec.get('shell-args', [])})
76 return variants 59 return variants
77 60
78 61
79 def _run_benchmark(shell, shell_args, app, duration_seconds, measurements,
80 verbose, android, output_file):
81 """Runs the given benchmark by running `benchmark.mojo` in mojo shell with
82 appropriate arguments and returns the produced output.
83
84 Returns:
85 A tuple of (succeeded, error_msg, output).
86 """
87 timeout = duration_seconds + _EXTRA_TIMEOUT
88 benchmark_args = []
89 benchmark_args.append('--app=' + app)
90 benchmark_args.append('--duration=' + str(duration_seconds))
91
92 device_output_file = None
93 if output_file:
94 if android:
95 device_output_file = os.path.join(shell.get_tmp_dir_path(), output_file)
96 benchmark_args.append('--trace-output=' + device_output_file)
97 else:
98 benchmark_args.append('--trace-output=' + output_file)
99
100 for measurement in measurements:
101 benchmark_args.append(measurement['spec'])
102
103 shell_args = list(shell_args)
104 shell_args.append(_BENCHMARK_APP)
105 shell_args.append('--force-offline-by-default')
106 shell_args.append('--args-for=%s %s' % (_BENCHMARK_APP,
107 ' '.join(benchmark_args)))
108
109 if verbose:
110 print 'shell arguments: ' + str(shell_args)
111 return_code, output, did_time_out = shell.run_and_get_output(
112 shell_args, timeout=timeout)
113
114 if did_time_out:
115 return False, 'timed out', output
116 if return_code:
117 return False, 'return code: ' + str(return_code), output
118
119 # Pull the trace file even if some measurements are missing, as it can be
120 # useful in debugging.
121 if device_output_file:
122 shell.pull_file(device_output_file, output_file, remove_original=True)
123
124 return True, None, output
125
126
127 def _parse_measurement_results(output):
128 """Parses the measurement results present in the benchmark output and returns
129 the dictionary of correctly recognized and parsed results.
130 """
131 measurement_results = {}
132 output_lines = [line.strip() for line in output.split('\n')]
133 for line in output_lines:
134 match = re.match(_MEASUREMENT_REGEX, line)
135 if match:
136 measurement_spec = match.group(1)
137 measurement_result = match.group(2)
138 try:
139 measurement_results[measurement_spec] = float(measurement_result)
140 except ValueError:
141 pass
142 return measurement_results
143
144
145 def main(): 62 def main():
146 parser = argparse.ArgumentParser( 63 parser = argparse.ArgumentParser(
147 formatter_class=argparse.RawDescriptionHelpFormatter, 64 formatter_class=argparse.RawDescriptionHelpFormatter,
148 description=_DESCRIPTION) 65 description=_DESCRIPTION)
149 parser.add_argument('benchmark_list_file', type=file, 66 parser.add_argument('benchmark_list_file', type=file,
150 help='a file listing benchmarks to run') 67 help='a file listing benchmarks to run')
151 parser.add_argument('--save-all-traces', action='store_true', 68 parser.add_argument('--save-all-traces', action='store_true',
152 help='save the traces produced by benchmarks to disk') 69 help='save the traces produced by benchmarks to disk')
153 perf_dashboard.add_argparse_server_arguments(parser) 70 perf_dashboard.add_argparse_server_arguments(parser)
154 71
(...skipping 28 matching lines...) Expand all
183 output_file = 'benchmark-%s-%s-%s.trace' % ( 100 output_file = 'benchmark-%s-%s-%s.trace' % (
184 benchmark_name.replace(' ', '_'), 101 benchmark_name.replace(' ', '_'),
185 variant_name.replace(' ', '_'), 102 variant_name.replace(' ', '_'),
186 time.strftime('%Y%m%d%H%M%S')) 103 time.strftime('%Y%m%d%H%M%S'))
187 104
188 chart_data_recorder = None 105 chart_data_recorder = None
189 if script_args.upload: 106 if script_args.upload:
190 chart_data_recorder = perf_dashboard.ChartDataRecorder( 107 chart_data_recorder = perf_dashboard.ChartDataRecorder(
191 script_args.test_name) 108 script_args.test_name)
192 109
193 benchmark_succeeded, benchmark_error, output = _run_benchmark( 110 results = benchmark.run(
194 shell, shell_args, app, duration, measurements, script_args.verbose, 111 shell, shell_args, app, duration, measurements, script_args.verbose,
195 script_args.android, output_file) 112 script_args.android, output_file)
196 113
197 print '[ %s ] %s ' % (benchmark_name, variant_name) 114 print '[ %s ] %s ' % (benchmark_name, variant_name)
198 115
199 some_measurements_failed = False 116 some_measurements_failed = False
200 some_measurements_succeeded = False 117 some_measurements_succeeded = False
201 if benchmark_succeeded: 118 if results.succeeded:
202 measurement_results = _parse_measurement_results(output)
203 # Iterate over the list of specs, not the dictionary, to detect missing 119 # Iterate over the list of specs, not the dictionary, to detect missing
204 # results and preserve the required order. 120 # results and preserve the required order.
205 for measurement in measurements: 121 for measurement in measurements:
206 if measurement['spec'] in measurement_results: 122 if measurement['spec'] in results.measurements:
207 result = measurement_results[measurement['spec']] 123 result = results.measurements[measurement['spec']]
208 print '%10.4f %s' % (result, measurement['name']) 124 print '%10.4f %s' % (result, measurement['name'])
209 125
210 if chart_data_recorder: 126 if chart_data_recorder:
211 chart_name = benchmark_name + '__' + variant_name 127 chart_name = benchmark_name + '__' + variant_name
212 chart_data_recorder.record_scalar( 128 chart_data_recorder.record_scalar(
213 perf_dashboard.normalize_label(chart_name), 129 perf_dashboard.normalize_label(chart_name),
214 perf_dashboard.normalize_label(measurement['name']), 130 perf_dashboard.normalize_label(measurement['name']),
215 'ms', result) 131 'ms', result)
216 some_measurements_succeeded = True 132 some_measurements_succeeded = True
217 else: 133 else:
218 print '? %s' % measurement['name'] 134 print '? %s' % measurement['name']
219 some_measurements_failed = True 135 some_measurements_failed = True
220 136
221 if not benchmark_succeeded or some_measurements_failed: 137 if not results.succeeded or some_measurements_failed:
222 if not benchmark_succeeded: 138 if not results.succeeded:
223 print 'benchmark failed: ' + benchmark_error 139 print 'benchmark failed: ' + results.error_str
224 if some_measurements_failed: 140 if some_measurements_failed:
225 print 'some measurements failed' 141 print 'some measurements failed'
226 print 'output: ' 142 print 'output: '
227 print '-' * 72 143 print '-' * 72
228 print output 144 print results.output
229 print '-' * 72 145 print '-' * 72
230 exit_code = 1 146 exit_code = 1
231 147
232 if script_args.upload and some_measurements_succeeded: 148 if script_args.upload and some_measurements_succeeded:
233 if not perf_dashboard.upload_chart_data( 149 if not perf_dashboard.upload_chart_data(
234 script_args.master_name, script_args.bot_name, 150 script_args.master_name, script_args.bot_name,
235 script_args.test_name, script_args.builder_name, 151 script_args.test_name, script_args.builder_name,
236 script_args.build_number, chart_data_recorder.get_chart_data(), 152 script_args.build_number, chart_data_recorder.get_chart_data(),
237 script_args.server_url, script_args.dry_run): 153 script_args.server_url, script_args.dry_run):
238 exit_code = 1 154 exit_code = 1
239 155
240 return exit_code 156 return exit_code
241 157
242 if __name__ == '__main__': 158 if __name__ == '__main__':
243 sys.exit(main()) 159 sys.exit(main())
OLDNEW
« no previous file with comments | « mojo/devtools/common/devtoolslib/benchmark_unittest.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698