blob: ec07e7c7e454464c85976753302e5cfa5bc59961 [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
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080030
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080031def SetupParserOptions(parser):
32 """Add all options to the parser."""
Manoj Guptaaee96b72016-10-24 13:43:28 -070033 parser.add_argument(
34 '--dry_run',
35 dest='dry_run',
36 help=('Parse the experiment file and '
37 'show what will be done'),
38 action='store_true',
39 default=False)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080040 # Allow each of the global fields to be overridden by passing in
41 # options. Add each global field as an option.
Luis Lozanof2a3ef42015-12-15 13:49:30 -080042 option_settings = GlobalSettings('')
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080043 for field_name in option_settings.fields:
44 field = option_settings.fields[field_name]
Manoj Guptaaee96b72016-10-24 13:43:28 -070045 parser.add_argument(
46 '--%s' % field.name,
47 dest=field.name,
48 help=field.description,
49 action='store')
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080050
51
52def ConvertOptionsToSettings(options):
53 """Convert options passed in into global settings."""
Luis Lozanof2a3ef42015-12-15 13:49:30 -080054 option_settings = GlobalSettings('option_settings')
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080055 for option_name in options.__dict__:
56 if (options.__dict__[option_name] is not None and
57 option_name in option_settings.fields):
58 option_settings.SetField(option_name, options.__dict__[option_name])
59 return option_settings
60
61
62def Cleanup(experiment):
63 """Handler function which is registered to the atexit handler."""
64 experiment.Cleanup()
65
66
Luis Lozano45b53c52015-09-30 11:36:27 -070067def CallExitHandler(signum, _):
68 """Signal handler that transforms a signal into a call to exit.
69
70 This is useful because functionality registered by "atexit" will
71 be called. It also means you can "catch" the signal by catching
72 the SystemExit exception.
73 """
74 sys.exit(128 + signum)
75
76
Manoj Guptaaee96b72016-10-24 13:43:28 -070077def RunCrosperf(argv):
Rahul Chaudhry4f07bbf2016-01-29 15:10:02 -080078 parser = argparse.ArgumentParser()
Luis Lozanof81680c2013-03-15 14:44:13 -070079
Manoj Guptaaee96b72016-10-24 13:43:28 -070080 parser.add_argument(
81 '--noschedv2',
82 dest='noschedv2',
83 default=False,
84 action='store_true',
85 help=('Do not use new scheduler. '
86 'Use original scheduler instead.'))
87 parser.add_argument(
88 '-l',
89 '--log_dir',
90 dest='log_dir',
91 default='',
92 help='The log_dir, default is under <crosperf_logs>/logs')
Luis Lozanof81680c2013-03-15 14:44:13 -070093
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080094 SetupParserOptions(parser)
Rahul Chaudhry4f07bbf2016-01-29 15:10:02 -080095 options, args = parser.parse_known_args(argv)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080096
97 # Convert the relevant options that are passed in into a settings
98 # object which will override settings in the experiment file.
99 option_settings = ConvertOptionsToSettings(options)
Luis Lozanof81680c2013-03-15 14:44:13 -0700100 log_dir = os.path.abspath(os.path.expanduser(options.log_dir))
101 logger.GetLogger(log_dir)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800102
103 if len(args) == 2:
104 experiment_filename = args[1]
105 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800106 parser.error('Invalid number arguments.')
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800107
108 working_directory = os.getcwd()
Ahmad Sharif4467f002012-12-20 12:09:49 -0800109 if options.dry_run:
110 test_flag.SetTestMode(True)
111
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800112 experiment_file = ExperimentFile(
Zhizhou Yang5534af82020-01-15 16:25:04 -0800113 open(experiment_filename, encoding='utf-8'), option_settings)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800114 if not experiment_file.GetGlobalSettings().GetField('name'):
Ahmad Sharif822c55d2012-02-08 20:55:47 -0800115 experiment_name = os.path.basename(experiment_filename)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800116 experiment_file.GetGlobalSettings().SetField('name', experiment_name)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800117 experiment = ExperimentFactory().GetExperiment(experiment_file,
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800118 working_directory, log_dir)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800119
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800120 json_report = experiment_file.GetGlobalSettings().GetField('json_report')
Caroline Ticeef4ca8a2015-08-25 12:53:38 -0700121
Luis Lozano45b53c52015-09-30 11:36:27 -0700122 signal.signal(signal.SIGTERM, CallExitHandler)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800123 atexit.register(Cleanup, experiment)
124
125 if options.dry_run:
Caroline Tice6e8726d2015-12-09 12:42:13 -0800126 runner = MockExperimentRunner(experiment, json_report)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800127 else:
Manoj Guptaaee96b72016-10-24 13:43:28 -0700128 runner = ExperimentRunner(
129 experiment, json_report, using_schedv2=(not options.noschedv2))
Han Shenba649282015-08-05 17:19:55 -0700130
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800131 runner.Run()
132
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800133
Manoj Guptaaee96b72016-10-24 13:43:28 -0700134def Main(argv):
135 try:
136 RunCrosperf(argv)
Tiancong Wangeb729be2019-08-07 15:18:51 -0700137 except Exception:
Manoj Guptaaee96b72016-10-24 13:43:28 -0700138 # Flush buffers before exiting to avoid out of order printing
139 sys.stdout.flush()
Tiancong Wangeb729be2019-08-07 15:18:51 -0700140 # Raise exception prints out traceback
141 raise
Manoj Guptaaee96b72016-10-24 13:43:28 -0700142
143
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800144if __name__ == '__main__':
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800145 Main(sys.argv)