1#!/usr/bin/env python3 2# -*- 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. 6 7"""The driver script for running performance benchmarks on ChromeOS.""" 8 9from __future__ import print_function 10 11import argparse 12import atexit 13import os 14import signal 15import sys 16 17from experiment_runner import ExperimentRunner 18from experiment_runner import MockExperimentRunner 19from experiment_factory import ExperimentFactory 20from experiment_file import ExperimentFile 21from settings_factory import GlobalSettings 22 23# 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. 25# pylint: disable=no-name-in-module 26from cros_utils import logger 27 28import test_flag 29 30 31def SetupParserOptions(parser): 32 """Add all options to the parser.""" 33 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) 40 # Allow each of the global fields to be overridden by passing in 41 # options. Add each global field as an option. 42 option_settings = GlobalSettings('') 43 for field_name in option_settings.fields: 44 field = option_settings.fields[field_name] 45 parser.add_argument( 46 '--%s' % field.name, 47 dest=field.name, 48 help=field.description, 49 action='store') 50 51 52def ConvertOptionsToSettings(options): 53 """Convert options passed in into global settings.""" 54 option_settings = GlobalSettings('option_settings') 55 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 67def 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 77def RunCrosperf(argv): 78 parser = argparse.ArgumentParser() 79 80 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') 93 94 SetupParserOptions(parser) 95 options, args = parser.parse_known_args(argv) 96 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) 100 log_dir = os.path.abspath(os.path.expanduser(options.log_dir)) 101 logger.GetLogger(log_dir) 102 103 if len(args) == 2: 104 experiment_filename = args[1] 105 else: 106 parser.error('Invalid number arguments.') 107 108 working_directory = os.getcwd() 109 if options.dry_run: 110 test_flag.SetTestMode(True) 111 112 experiment_file = ExperimentFile( 113 open(experiment_filename, encoding='utf-8'), option_settings) 114 if not experiment_file.GetGlobalSettings().GetField('name'): 115 experiment_name = os.path.basename(experiment_filename) 116 experiment_file.GetGlobalSettings().SetField('name', experiment_name) 117 experiment = ExperimentFactory().GetExperiment(experiment_file, 118 working_directory, log_dir) 119 120 json_report = experiment_file.GetGlobalSettings().GetField('json_report') 121 122 signal.signal(signal.SIGTERM, CallExitHandler) 123 atexit.register(Cleanup, experiment) 124 125 if options.dry_run: 126 runner = MockExperimentRunner(experiment, json_report) 127 else: 128 runner = ExperimentRunner( 129 experiment, json_report, using_schedv2=(not options.noschedv2)) 130 131 runner.Run() 132 133 134def Main(argv): 135 try: 136 RunCrosperf(argv) 137 except Exception: 138 # Flush buffers before exiting to avoid out of order printing 139 sys.stdout.flush() 140 # Raise exception prints out traceback 141 raise 142 143 144if __name__ == '__main__': 145 Main(sys.argv) 146