blob: b6c17aeb2eaad32722256726c3044f9c2522df99 [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Runner for Mojo application benchmarks."""
import argparse
import logging
import sys
import time
from devtoolslib import benchmark
from devtoolslib import perf_dashboard
from devtoolslib import shell_arguments
from devtoolslib import shell_config
_DESCRIPTION = """Runner for Mojo application benchmarks.
|benchmark_list_file| has to be a valid Python program that sets a |benchmarks|
dictionary. For description of the required format see
https://github.com/domokit/devtools/blob/master/docs/mojo_benchmark.md .
"""
_logger = logging.getLogger()
_CACHE_SERVICE_URL = 'mojo:url_response_disk_cache'
_NETWORK_SERVICE_URL = 'mojo:network_service'
_COLD_START_SHELL_ARGS = [
'--args-for=%s %s' % (_CACHE_SERVICE_URL, '--clear'),
'--args-for=%s %s' % (_NETWORK_SERVICE_URL, '--clear'),
]
def _generate_benchmark_variants(benchmark_spec):
"""Generates benchmark specifications for individual variants of the given
benchmark: cold start and warm start.
Returns:
A list of benchmark specs corresponding to individual variants of the given
benchmark.
"""
variants = []
variants.append({
'variant_name': 'cold start',
'app': benchmark_spec['app'],
'duration': benchmark_spec['duration'],
'measurements': benchmark_spec['measurements'],
'shell-args': benchmark_spec.get('shell-args',
[]) + _COLD_START_SHELL_ARGS})
variants.append({
'variant_name': 'warm start',
'app': benchmark_spec['app'],
'duration': benchmark_spec['duration'],
'measurements': benchmark_spec['measurements'],
'shell-args': benchmark_spec.get('shell-args', [])})
return variants
def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=_DESCRIPTION)
parser.add_argument('benchmark_list_file', type=file,
help='a file listing benchmarks to run')
parser.add_argument('--save-all-traces', action='store_true',
help='save the traces produced by benchmarks to disk')
perf_dashboard.add_argparse_server_arguments(parser)
# Common shell configuration arguments.
shell_config.add_shell_arguments(parser)
script_args = parser.parse_args()
config = shell_config.get_shell_config(script_args)
try:
shell, common_shell_args = shell_arguments.get_shell(config, [])
except shell_arguments.ShellConfigurationException as e:
print e
return 1
target_os = 'android' if script_args.android else 'linux'
benchmark_list_params = {"target_os": target_os}
exec script_args.benchmark_list_file in benchmark_list_params
exit_code = 0
for benchmark_spec in benchmark_list_params['benchmarks']:
benchmark_name = benchmark_spec['name']
for variant_spec in _generate_benchmark_variants(benchmark_spec):
variant_name = variant_spec['variant_name']
app = variant_spec['app']
duration = variant_spec['duration']
shell_args = variant_spec.get('shell-args', []) + common_shell_args
measurements = variant_spec['measurements']
output_file = None
if script_args.save_all_traces:
output_file = 'benchmark-%s-%s-%s.trace' % (
benchmark_name.replace(' ', '_'),
variant_name.replace(' ', '_'),
time.strftime('%Y%m%d%H%M%S'))
chart_data_recorder = None
if script_args.upload:
chart_data_recorder = perf_dashboard.ChartDataRecorder(
script_args.test_name)
results = benchmark.run(
shell, shell_args, app, duration, measurements, script_args.verbose,
script_args.android, output_file)
print '[ %s ] %s ' % (benchmark_name, variant_name)
some_measurements_failed = False
some_measurements_succeeded = False
if results.succeeded:
# Iterate over the list of specs, not the dictionary, to detect missing
# results and preserve the required order.
for measurement in measurements:
if measurement['spec'] in results.measurements:
result = results.measurements[measurement['spec']]
print '%10.4f %s' % (result, measurement['name'])
if chart_data_recorder:
chart_name = benchmark_name + '__' + variant_name
chart_data_recorder.record_scalar(
perf_dashboard.normalize_label(chart_name),
perf_dashboard.normalize_label(measurement['name']),
'ms', result)
some_measurements_succeeded = True
else:
print '? %s' % measurement['name']
some_measurements_failed = True
if not results.succeeded or some_measurements_failed:
if not results.succeeded:
print 'benchmark failed: ' + results.error_str
if some_measurements_failed:
print 'some measurements failed'
print 'output: '
print '-' * 72
print results.output
print '-' * 72
exit_code = 1
if script_args.upload and some_measurements_succeeded:
if not perf_dashboard.upload_chart_data(
script_args.master_name, script_args.bot_name,
script_args.test_name, script_args.builder_name,
script_args.build_number, chart_data_recorder.get_chart_data(),
script_args.server_url, script_args.dry_run):
exit_code = 1
return exit_code
if __name__ == '__main__':
sys.exit(main())