blob: f195b13a02a89dafe7ba68926df825d6e9e52a2f [file] [log] [blame]
Zhizhou Yang5534af82020-01-15 16:25:04 -08001#!/usr/bin/env python3
Tiancong Wangeb729be2019-08-07 15:18:51 -07002# -*- coding: utf-8 -*-
3# Copyright 2011 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -08006
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -08007"""The driver script for running performance benchmarks on ChromeOS."""
8
Rahul Chaudhrycbc5a262015-12-30 17:05:14 -08009from __future__ import print_function
10
Rahul Chaudhry4f07bbf2016-01-29 15:10:02 -080011import argparse
Denis Nikitin144f6992019-07-20 20:25:16 -070012import atexit
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080013import os
Luis Lozano45b53c52015-09-30 11:36:27 -070014import signal
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080015import sys
Tiancong Wangeb729be2019-08-07 15:18:51 -070016
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080017from experiment_runner import ExperimentRunner
18from experiment_runner import MockExperimentRunner
19from experiment_factory import ExperimentFactory
20from experiment_file import ExperimentFile
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080021from settings_factory import GlobalSettings
Rahul Chaudhryeff2fc12016-02-24 10:12:43 -080022
Caroline Ticea8af9a72016-07-20 12:52:59 -070023# This import causes pylint to warn about "No name 'logger' in module
24# 'cros_utils'". I do not understand why. The import works fine in python.
Rahul Chaudhryeff2fc12016-02-24 10:12:43 -080025# pylint: disable=no-name-in-module
Caroline Ticea8af9a72016-07-20 12:52:59 -070026from cros_utils import logger
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080027
Ahmad Sharif4467f002012-12-20 12:09:49 -080028import test_flag
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080029
zhizhouy7ee1e5d2020-03-24 17:11:45 -070030HAS_FAILURE = 1
31ALL_FAILED = 2
32
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080033
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080034def SetupParserOptions(parser):
35 """Add all options to the parser."""
Manoj Guptaaee96b72016-10-24 13:43:28 -070036 parser.add_argument(
37 '--dry_run',
38 dest='dry_run',
39 help=('Parse the experiment file and '
40 'show what will be done'),
41 action='store_true',
42 default=False)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080043 # Allow each of the global fields to be overridden by passing in
44 # options. Add each global field as an option.
Luis Lozanof2a3ef42015-12-15 13:49:30 -080045 option_settings = GlobalSettings('')
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080046 for field_name in option_settings.fields:
47 field = option_settings.fields[field_name]
Manoj Guptaaee96b72016-10-24 13:43:28 -070048 parser.add_argument(
49 '--%s' % field.name,
50 dest=field.name,
51 help=field.description,
52 action='store')
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080053
54
55def ConvertOptionsToSettings(options):
56 """Convert options passed in into global settings."""
Luis Lozanof2a3ef42015-12-15 13:49:30 -080057 option_settings = GlobalSettings('option_settings')
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080058 for option_name in options.__dict__:
59 if (options.__dict__[option_name] is not None and
60 option_name in option_settings.fields):
61 option_settings.SetField(option_name, options.__dict__[option_name])
62 return option_settings
63
64
65def Cleanup(experiment):
66 """Handler function which is registered to the atexit handler."""
67 experiment.Cleanup()
68
69
Luis Lozano45b53c52015-09-30 11:36:27 -070070def CallExitHandler(signum, _):
71 """Signal handler that transforms a signal into a call to exit.
72
73 This is useful because functionality registered by "atexit" will
74 be called. It also means you can "catch" the signal by catching
75 the SystemExit exception.
76 """
77 sys.exit(128 + signum)
78
79
Manoj Guptaaee96b72016-10-24 13:43:28 -070080def RunCrosperf(argv):
Rahul Chaudhry4f07bbf2016-01-29 15:10:02 -080081 parser = argparse.ArgumentParser()
Luis Lozanof81680c2013-03-15 14:44:13 -070082
Manoj Guptaaee96b72016-10-24 13:43:28 -070083 parser.add_argument(
84 '--noschedv2',
85 dest='noschedv2',
86 default=False,
87 action='store_true',
88 help=('Do not use new scheduler. '
89 'Use original scheduler instead.'))
90 parser.add_argument(
91 '-l',
92 '--log_dir',
93 dest='log_dir',
94 default='',
95 help='The log_dir, default is under <crosperf_logs>/logs')
Luis Lozanof81680c2013-03-15 14:44:13 -070096
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080097 SetupParserOptions(parser)
Rahul Chaudhry4f07bbf2016-01-29 15:10:02 -080098 options, args = parser.parse_known_args(argv)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080099
100 # Convert the relevant options that are passed in into a settings
101 # object which will override settings in the experiment file.
102 option_settings = ConvertOptionsToSettings(options)
Luis Lozanof81680c2013-03-15 14:44:13 -0700103 log_dir = os.path.abspath(os.path.expanduser(options.log_dir))
104 logger.GetLogger(log_dir)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800105
106 if len(args) == 2:
107 experiment_filename = args[1]
108 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800109 parser.error('Invalid number arguments.')
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800110
111 working_directory = os.getcwd()
Ahmad Sharif4467f002012-12-20 12:09:49 -0800112 if options.dry_run:
113 test_flag.SetTestMode(True)
114
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800115 experiment_file = ExperimentFile(
Zhizhou Yang5534af82020-01-15 16:25:04 -0800116 open(experiment_filename, encoding='utf-8'), option_settings)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800117 if not experiment_file.GetGlobalSettings().GetField('name'):
Ahmad Sharif822c55d2012-02-08 20:55:47 -0800118 experiment_name = os.path.basename(experiment_filename)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800119 experiment_file.GetGlobalSettings().SetField('name', experiment_name)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800120 experiment = ExperimentFactory().GetExperiment(experiment_file,
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800121 working_directory, log_dir)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800122
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800123 json_report = experiment_file.GetGlobalSettings().GetField('json_report')
Caroline Ticeef4ca8a2015-08-25 12:53:38 -0700124
Luis Lozano45b53c52015-09-30 11:36:27 -0700125 signal.signal(signal.SIGTERM, CallExitHandler)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800126 atexit.register(Cleanup, experiment)
127
128 if options.dry_run:
Caroline Tice6e8726d2015-12-09 12:42:13 -0800129 runner = MockExperimentRunner(experiment, json_report)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800130 else:
Manoj Guptaaee96b72016-10-24 13:43:28 -0700131 runner = ExperimentRunner(
132 experiment, json_report, using_schedv2=(not options.noschedv2))
Han Shenba649282015-08-05 17:19:55 -0700133
zhizhouy7ee1e5d2020-03-24 17:11:45 -0700134 ret = runner.Run()
135 if ret == HAS_FAILURE:
136 raise RuntimeError('One or more benchmarks failed.')
137 if ret == ALL_FAILED:
138 raise RuntimeError('All benchmarks failed to run.')
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800139
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800140
Manoj Guptaaee96b72016-10-24 13:43:28 -0700141def Main(argv):
142 try:
143 RunCrosperf(argv)
Tiancong Wangeb729be2019-08-07 15:18:51 -0700144 except Exception:
Manoj Guptaaee96b72016-10-24 13:43:28 -0700145 # Flush buffers before exiting to avoid out of order printing
146 sys.stdout.flush()
Tiancong Wangeb729be2019-08-07 15:18:51 -0700147 # Raise exception prints out traceback
148 raise
Manoj Guptaaee96b72016-10-24 13:43:28 -0700149
150
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800151if __name__ == '__main__':
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800152 Main(sys.argv)