• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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