1#!/usr/bin/env python2 2 3# Copyright 2011 Google Inc. All Rights Reserved. 4"""The driver script for running performance benchmarks on ChromeOS.""" 5 6from __future__ import print_function 7 8import atexit 9import argparse 10import os 11import signal 12import sys 13from experiment_runner import ExperimentRunner 14from experiment_runner import MockExperimentRunner 15from experiment_factory import ExperimentFactory 16from experiment_file import ExperimentFile 17from settings_factory import GlobalSettings 18 19# This import causes pylint to warn about "No name 'logger' in module 20# 'cros_utils'". I do not understand why. The import works fine in python. 21# pylint: disable=no-name-in-module 22from cros_utils import logger 23 24import test_flag 25 26 27def SetupParserOptions(parser): 28 """Add all options to the parser.""" 29 parser.add_argument( 30 '--dry_run', 31 dest='dry_run', 32 help=('Parse the experiment file and ' 33 'show what will be done'), 34 action='store_true', 35 default=False) 36 # Allow each of the global fields to be overridden by passing in 37 # options. Add each global field as an option. 38 option_settings = GlobalSettings('') 39 for field_name in option_settings.fields: 40 field = option_settings.fields[field_name] 41 parser.add_argument( 42 '--%s' % field.name, 43 dest=field.name, 44 help=field.description, 45 action='store') 46 47 48def ConvertOptionsToSettings(options): 49 """Convert options passed in into global settings.""" 50 option_settings = GlobalSettings('option_settings') 51 for option_name in options.__dict__: 52 if (options.__dict__[option_name] is not None and 53 option_name in option_settings.fields): 54 option_settings.SetField(option_name, options.__dict__[option_name]) 55 return option_settings 56 57 58def Cleanup(experiment): 59 """Handler function which is registered to the atexit handler.""" 60 experiment.Cleanup() 61 62 63def CallExitHandler(signum, _): 64 """Signal handler that transforms a signal into a call to exit. 65 66 This is useful because functionality registered by "atexit" will 67 be called. It also means you can "catch" the signal by catching 68 the SystemExit exception. 69 """ 70 sys.exit(128 + signum) 71 72 73def RunCrosperf(argv): 74 parser = argparse.ArgumentParser() 75 76 parser.add_argument( 77 '--noschedv2', 78 dest='noschedv2', 79 default=False, 80 action='store_true', 81 help=('Do not use new scheduler. ' 82 'Use original scheduler instead.')) 83 parser.add_argument( 84 '-l', 85 '--log_dir', 86 dest='log_dir', 87 default='', 88 help='The log_dir, default is under <crosperf_logs>/logs') 89 90 SetupParserOptions(parser) 91 options, args = parser.parse_known_args(argv) 92 93 # Convert the relevant options that are passed in into a settings 94 # object which will override settings in the experiment file. 95 option_settings = ConvertOptionsToSettings(options) 96 log_dir = os.path.abspath(os.path.expanduser(options.log_dir)) 97 logger.GetLogger(log_dir) 98 99 if len(args) == 2: 100 experiment_filename = args[1] 101 else: 102 parser.error('Invalid number arguments.') 103 104 working_directory = os.getcwd() 105 if options.dry_run: 106 test_flag.SetTestMode(True) 107 108 experiment_file = ExperimentFile( 109 open(experiment_filename, 'rb'), option_settings) 110 if not experiment_file.GetGlobalSettings().GetField('name'): 111 experiment_name = os.path.basename(experiment_filename) 112 experiment_file.GetGlobalSettings().SetField('name', experiment_name) 113 experiment = ExperimentFactory().GetExperiment(experiment_file, 114 working_directory, log_dir) 115 116 json_report = experiment_file.GetGlobalSettings().GetField('json_report') 117 118 signal.signal(signal.SIGTERM, CallExitHandler) 119 atexit.register(Cleanup, experiment) 120 121 if options.dry_run: 122 runner = MockExperimentRunner(experiment, json_report) 123 else: 124 runner = ExperimentRunner( 125 experiment, json_report, using_schedv2=(not options.noschedv2)) 126 127 runner.Run() 128 129 130def Main(argv): 131 try: 132 RunCrosperf(argv) 133 except Exception as ex: 134 # Flush buffers before exiting to avoid out of order printing 135 sys.stdout.flush() 136 sys.stderr.flush() 137 print('Crosperf error: %s' % repr(ex)) 138 sys.stdout.flush() 139 sys.stderr.flush() 140 sys.exit(1) 141 142 143if __name__ == '__main__': 144 Main(sys.argv) 145