Home | History | Annotate | Download | only in crosperf
      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 
      6 from __future__ import print_function
      7 
      8 import atexit
      9 import argparse
     10 import os
     11 import signal
     12 import sys
     13 from experiment_runner import ExperimentRunner
     14 from experiment_runner import MockExperimentRunner
     15 from experiment_factory import ExperimentFactory
     16 from experiment_file import ExperimentFile
     17 from 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
     22 from cros_utils import logger
     23 
     24 import test_flag
     25 
     26 
     27 def 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 
     48 def 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 
     58 def Cleanup(experiment):
     59   """Handler function which is registered to the atexit handler."""
     60   experiment.Cleanup()
     61 
     62 
     63 def 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 
     73 def 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 
    130 def 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 
    143 if __name__ == '__main__':
    144   Main(sys.argv)
    145