[tools] Migrate to argparse module and remove few deprecated arguments

The --run-count-multiplier flag was used to run an experiment and is not needed
anymore. It will be superceeded by another parameter that will run benchmarks as
many times as needed until needed confidence is achieved.

R=machenbach@chromium.org

No-Try: true
No-Tree-Checks: true
Bug: chromium:880724
Change-Id: Iedd3d0f900a838f97cfa3339f582f6d02cce3e93
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1578504
Commit-Queue: Sergiy Belozorov <sergiyb@chromium.org>
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60980}
This commit is contained in:
Sergiy Belozorov 2019-04-23 18:42:23 +02:00 committed by Commit Bot
parent 73212783fb
commit 2caf6d0a5e

View File

@ -112,7 +112,7 @@ import copy
import json
import logging
import math
import optparse
import argparse
import os
import re
import subprocess
@ -130,7 +130,6 @@ try:
except NameError: # Python 3
basestring = str
ARCH_GUESS = utils.DefaultArch()
SUPPORTED_ARCHS = ['arm',
'ia32',
'mips',
@ -578,26 +577,26 @@ def FlattenRunnables(node, node_cb):
class Platform(object):
def __init__(self, options):
self.shell_dir = options.shell_dir
self.shell_dir_secondary = options.shell_dir_secondary
self.extra_flags = options.extra_flags.split()
self.options = options
def __init__(self, args):
self.shell_dir = args.shell_dir
self.shell_dir_secondary = args.shell_dir_secondary
self.extra_flags = args.extra_flags.split()
self.args = args
@staticmethod
def ReadBuildConfig(options):
config_path = os.path.join(options.shell_dir, 'v8_build_config.json')
def ReadBuildConfig(args):
config_path = os.path.join(args.shell_dir, 'v8_build_config.json')
if not os.path.isfile(config_path):
return {}
with open(config_path) as f:
return json.load(f)
@staticmethod
def GetPlatform(options):
if Platform.ReadBuildConfig(options).get('is_android', False):
return AndroidPlatform(options)
def GetPlatform(args):
if Platform.ReadBuildConfig(args).get('is_android', False):
return AndroidPlatform(args)
else:
return DesktopPlatform(options)
return DesktopPlatform(args)
def _Run(self, runnable, count, secondary=False):
raise NotImplementedError() # pragma: no cover
@ -627,13 +626,13 @@ class Platform(object):
def Run(self, runnable, count):
"""Execute the benchmark's main file.
If options.shell_dir_secondary is specified, the benchmark is run twice,
e.g. with and without patch.
If args.shell_dir_secondary is specified, the benchmark is run twice, e.g.
with and without patch.
Args:
runnable: A Runnable benchmark instance.
count: The number of this (repeated) run.
Returns: A tuple with the two benchmark outputs. The latter will be None if
options.shell_dir_secondary was not specified.
args.shell_dir_secondary was not specified.
"""
output = self._LoggedRun(runnable, count, secondary=False)
if self.shell_dir_secondary:
@ -643,23 +642,23 @@ class Platform(object):
class DesktopPlatform(Platform):
def __init__(self, options):
super(DesktopPlatform, self).__init__(options)
def __init__(self, args):
super(DesktopPlatform, self).__init__(args)
self.command_prefix = []
# Setup command class to OS specific version.
command.setup(utils.GuessOS(), options.device)
command.setup(utils.GuessOS(), args.device)
if options.prioritize or options.affinitize != None:
if args.prioritize or args.affinitize != None:
self.command_prefix = ['schedtool']
if options.prioritize:
if args.prioritize:
self.command_prefix += ['-n', '-20']
if options.affinitize != None:
if args.affinitize != None:
# schedtool expects a bit pattern when setting affinity, where each
# bit set to '1' corresponds to a core where the process may run on.
# First bit corresponds to CPU 0. Since the 'affinitize' parameter is
# a core number, we need to map to said bit pattern.
cpu = int(options.affinitize)
cpu = int(args.affinitize)
core = 1 << cpu
self.command_prefix += ['-a', ('0x%x' % core)]
self.command_prefix += ['-e']
@ -696,9 +695,9 @@ class DesktopPlatform(Platform):
class AndroidPlatform(Platform): # pragma: no cover
def __init__(self, options):
super(AndroidPlatform, self).__init__(options)
self.driver = android.android_driver(options.device)
def __init__(self, args):
super(AndroidPlatform, self).__init__(args)
self.driver = android.android_driver(args.device)
def PreExecution(self):
self.driver.set_high_perf_mode()
@ -739,10 +738,10 @@ class AndroidPlatform(Platform): # pragma: no cover
bench_rel = '.'
logcat_file = None
if self.options.dump_logcats_to:
if self.args.dump_logcats_to:
runnable_name = '-'.join(runnable.graphs)
logcat_file = os.path.join(
self.options.dump_logcats_to, 'logcat-%s-#%d%s.log' % (
self.args.dump_logcats_to, 'logcat-%s-#%d%s.log' % (
runnable_name, count + 1, '-secondary' if secondary else ''))
logging.debug('Dumping logcat into %s', logcat_file)
@ -872,144 +871,137 @@ class CustomMachineConfiguration:
raise Exception('Could not set CPU governor. Present value is %s'
% cur_value )
def Main(args):
parser = optparse.OptionParser()
parser.add_option('--android-build-tools', help='Deprecated.')
parser.add_option('--arch',
help=('The architecture to run tests for, '
'"auto" or "native" for auto-detect'),
default='x64')
parser.add_option('--buildbot',
help='Adapt to path structure used on buildbots and adds '
'timestamps/level to all logged status messages',
default=False, action='store_true')
parser.add_option('-d', '--device',
help='The device ID to run Android tests on. If not given '
'it will be autodetected.')
parser.add_option('--extra-flags',
help='Additional flags to pass to the test executable',
default='')
parser.add_option('--json-test-results',
help='Path to a file for storing json results.')
parser.add_option('--json-test-results-secondary',
'--json-test-results-no-patch', # TODO(sergiyb): Deprecate.
help='Path to a file for storing json results from run '
'without patch or for reference build run.')
parser.add_option('--outdir', help='Base directory with compile output',
default='out')
parser.add_option('--outdir-secondary',
'--outdir-no-patch', # TODO(sergiyb): Deprecate.
help='Base directory with compile output without patch or '
'for reference build')
parser.add_option('--binary-override-path',
help='JavaScript engine binary. By default, d8 under '
'architecture-specific build dir. '
'Not supported in conjunction with outdir-secondary.')
parser.add_option('--prioritize',
help='Raise the priority to nice -20 for the benchmarking '
'process.Requires Linux, schedtool, and sudo privileges.',
default=False, action='store_true')
parser.add_option('--affinitize',
help='Run benchmarking process on the specified core. '
'For example: '
'--affinitize=0 will run the benchmark process on core 0. '
'--affinitize=3 will run the benchmark process on core 3. '
'Requires Linux, schedtool, and sudo privileges.',
default=None)
parser.add_option('--noaslr',
help='Disable ASLR for the duration of the benchmarked '
'process. Requires Linux and sudo privileges.',
default=False, action='store_true')
parser.add_option('--cpu-governor',
help='Set cpu governor to specified policy for the '
'duration of the benchmarked process. Typical options: '
'"powersave" for more stable results, or "performance" '
'for shorter completion time of suite, with potentially '
'more noise in results.')
parser.add_option('--filter',
help='Only run the benchmarks beginning with this string. '
'For example: '
'--filter=JSTests/TypedArrays/ will run only TypedArray '
'benchmarks from the JSTests suite.',
default='')
parser.add_option('--run-count-multiplier', default=1, type='int',
help='Multipled used to increase number of times each test '
'is retried.')
parser.add_option('--dump-logcats-to',
help='Writes logcat output from each test into specified '
'directory. Only supported for android targets.')
def Main(argv):
parser = argparse.ArgumentParser()
parser.add_argument('--arch',
help='The architecture to run tests for. Pass "auto" '
'to auto-detect.', default='x64',
choices=SUPPORTED_ARCHS + ['auto'])
parser.add_argument('--buildbot',
help='Adapt to path structure used on buildbots and adds '
'timestamps/level to all logged status messages',
default=False, action='store_true')
parser.add_argument('-d', '--device',
help='The device ID to run Android tests on. If not '
'given it will be autodetected.')
parser.add_argument('--extra-flags',
help='Additional flags to pass to the test executable',
default='')
parser.add_argument('--json-test-results',
help='Path to a file for storing json results.')
parser.add_argument('--json-test-results-secondary',
help='Path to a file for storing json results from run '
'without patch or for reference build run.')
parser.add_argument('--outdir', help='Base directory with compile output',
default='out')
parser.add_argument('--outdir-secondary',
help='Base directory with compile output without patch '
'or for reference build')
parser.add_argument('--binary-override-path',
help='JavaScript engine binary. By default, d8 under '
'architecture-specific build dir. '
'Not supported in conjunction with outdir-secondary.')
parser.add_argument('--prioritize',
help='Raise the priority to nice -20 for the '
'benchmarking process.Requires Linux, schedtool, and '
'sudo privileges.', default=False, action='store_true')
parser.add_argument('--affinitize',
help='Run benchmarking process on the specified core. '
'For example: --affinitize=0 will run the benchmark '
'process on core 0. --affinitize=3 will run the '
'benchmark process on core 3. Requires Linux, schedtool, '
'and sudo privileges.', default=None)
parser.add_argument('--noaslr',
help='Disable ASLR for the duration of the benchmarked '
'process. Requires Linux and sudo privileges.',
default=False, action='store_true')
parser.add_argument('--cpu-governor',
help='Set cpu governor to specified policy for the '
'duration of the benchmarked process. Typical options: '
'"powersave" for more stable results, or "performance" '
'for shorter completion time of suite, with potentially '
'more noise in results.')
parser.add_argument('--filter',
help='Only run the benchmarks beginning with this '
'string. For example: '
'--filter=JSTests/TypedArrays/ will run only TypedArray '
'benchmarks from the JSTests suite.',
default='')
parser.add_argument('--dump-logcats-to',
help='Writes logcat output from each test into specified '
'directory. Only supported for android targets.')
parser.add_argument('suite', nargs='+', help='Path to the suite config file.')
(options, args) = parser.parse_args(args)
try:
args = parser.parse_args(argv)
except SystemExit:
return INFRA_FAILURE_RETCODE
logging.basicConfig(
level=logging.INFO, format='%(asctime)s %(levelname)-8s %(message)s')
if len(args) == 0: # pragma: no cover
parser.print_help()
return INFRA_FAILURE_RETCODE
if args.arch == 'auto': # pragma: no cover
args.arch = utils.DefaultArch()
if args.arch not in SUPPORTED_ARCHS:
logging.error(
'Auto-detected architecture "%s" is not supported.', args.arch)
return INFRA_FAILURE_RETCODE
if options.arch in ['auto', 'native']: # pragma: no cover
options.arch = ARCH_GUESS
if not options.arch in SUPPORTED_ARCHS: # pragma: no cover
logging.error('Unknown architecture %s', options.arch)
return INFRA_FAILURE_RETCODE
if (options.json_test_results_secondary and
not options.outdir_secondary): # pragma: no cover
if (args.json_test_results_secondary and
not args.outdir_secondary): # pragma: no cover
logging.error('For writing secondary json test results, a secondary outdir '
'patch must be specified.')
return INFRA_FAILURE_RETCODE
workspace = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if options.buildbot:
if args.buildbot:
build_config = 'Release'
else:
build_config = '%s.release' % options.arch
build_config = '%s.release' % args.arch
if options.binary_override_path == None:
options.shell_dir = os.path.join(workspace, options.outdir, build_config)
if args.binary_override_path == None:
args.shell_dir = os.path.join(workspace, args.outdir, build_config)
default_binary_name = 'd8'
else:
if not os.path.isfile(options.binary_override_path):
if not os.path.isfile(args.binary_override_path):
logging.error('binary-override-path must be a file name')
return INFRA_FAILURE_RETCODE
if options.outdir_secondary:
if args.outdir_secondary:
logging.error('specify either binary-override-path or outdir-secondary')
return INFRA_FAILURE_RETCODE
options.shell_dir = os.path.abspath(
os.path.dirname(options.binary_override_path))
default_binary_name = os.path.basename(options.binary_override_path)
args.shell_dir = os.path.abspath(
os.path.dirname(args.binary_override_path))
default_binary_name = os.path.basename(args.binary_override_path)
if options.outdir_secondary:
options.shell_dir_secondary = os.path.join(
workspace, options.outdir_secondary, build_config)
if args.outdir_secondary:
args.shell_dir_secondary = os.path.join(
workspace, args.outdir_secondary, build_config)
else:
options.shell_dir_secondary = None
args.shell_dir_secondary = None
if options.json_test_results:
options.json_test_results = os.path.abspath(options.json_test_results)
if args.json_test_results:
args.json_test_results = os.path.abspath(args.json_test_results)
if options.json_test_results_secondary:
options.json_test_results_secondary = os.path.abspath(
options.json_test_results_secondary)
if args.json_test_results_secondary:
args.json_test_results_secondary = os.path.abspath(
args.json_test_results_secondary)
# Ensure all arguments have absolute path before we start changing current
# directory.
args = map(os.path.abspath, args)
args.suite = map(os.path.abspath, args.suite)
prev_aslr = None
prev_cpu_gov = None
platform = Platform.GetPlatform(options)
platform = Platform.GetPlatform(args)
results = Results()
results_secondary = Results()
# We use list here to allow modification in nested function below.
have_failed_tests = [False]
with CustomMachineConfiguration(governor = options.cpu_governor,
disable_aslr = options.noaslr) as conf:
for path in args:
with CustomMachineConfiguration(governor = args.cpu_governor,
disable_aslr = args.noaslr) as conf:
for path in args.suite:
if not os.path.exists(path): # pragma: no cover
results.errors.append('Configuration file %s does not exist.' % path)
continue
@ -1025,7 +1017,7 @@ def Main(args):
# Build the graph/trace tree structure.
default_parent = DefaultSentinel(default_binary_name)
root = BuildGraphConfigs(suite, options.arch, default_parent)
root = BuildGraphConfigs(suite, args.arch, default_parent)
# Callback to be called on each node on traversal.
def NodeCB(node):
@ -1034,8 +1026,8 @@ def Main(args):
# Traverse graph/trace tree and iterate over all runnables.
for runnable in FlattenRunnables(root, NodeCB):
runnable_name = '/'.join(runnable.graphs)
if (not runnable_name.startswith(options.filter) and
runnable_name + '/' != options.filter):
if (not runnable_name.startswith(args.filter) and
runnable_name + '/' != args.filter):
continue
logging.info('>>> Running suite: %s', runnable_name)
durations = []
@ -1043,8 +1035,7 @@ def Main(args):
def Runner():
"""Output generator that reruns several times."""
total_runs = runnable.run_count * options.run_count_multiplier
for i in range(0, max(1, total_runs)):
for i in range(0, max(1, runnable.run_count)):
attempts_left = runnable.retry_count + 1
while attempts_left:
output, output_secondary = platform.Run(runnable, i)
@ -1062,7 +1053,7 @@ def Main(args):
# Let runnable iterate over all runs and handle output.
result, result_secondary = runnable.Run(
Runner, trybot=options.shell_dir_secondary)
Runner, trybot=args.shell_dir_secondary)
results += result
results_secondary += result_secondary
if runnable.has_timeouts:
@ -1083,13 +1074,13 @@ def Main(args):
platform.PostExecution()
if options.json_test_results:
results.WriteToFile(options.json_test_results)
if args.json_test_results:
results.WriteToFile(args.json_test_results)
else: # pragma: no cover
print(results)
if options.json_test_results_secondary:
results_secondary.WriteToFile(options.json_test_results_secondary)
if args.json_test_results_secondary:
results_secondary.WriteToFile(args.json_test_results_secondary)
else: # pragma: no cover
print(results_secondary)