aboutsummaryrefslogtreecommitdiff
path: root/crosperf/experiment_factory.py
diff options
context:
space:
mode:
Diffstat (limited to 'crosperf/experiment_factory.py')
-rw-r--r--crosperf/experiment_factory.py331
1 files changed, 331 insertions, 0 deletions
diff --git a/crosperf/experiment_factory.py b/crosperf/experiment_factory.py
new file mode 100644
index 00000000..2278015b
--- /dev/null
+++ b/crosperf/experiment_factory.py
@@ -0,0 +1,331 @@
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""A module to generate experiments."""
+
+from __future__ import print_function
+import os
+import re
+import socket
+
+from benchmark import Benchmark
+import config
+from experiment import Experiment
+from label import Label
+from label import MockLabel
+from results_cache import CacheConditions
+import test_flag
+import file_lock_machine
+
+# Users may want to run Telemetry tests either individually, or in
+# specified sets. Here we define sets of tests that users may want
+# to run together.
+
+telemetry_perfv2_tests = [
+ 'dromaeo.domcoreattr', 'dromaeo.domcoremodify', 'dromaeo.domcorequery',
+ 'dromaeo.domcoretraverse', 'kraken', 'octane', 'robohornet_pro', 'sunspider'
+]
+
+telemetry_pagecycler_tests = [
+ 'page_cycler_v2.intl_ar_fa_he',
+ 'page_cycler_v2.intl_es_fr_pt-BR',
+ 'page_cycler_v2.intl_hi_ru',
+ 'page_cycler_v2.intl_ja_zh',
+ 'page_cycler_v2.intl_ko_th_vi',
+ # 'page_cycler_v2.morejs',
+ # 'page_cycler_v2.moz',
+ # 'page_cycler_v2.netsim.top_10',
+ 'page_cycler_v2.tough_layout_cases',
+ 'page_cycler_v2.typical_25'
+]
+
+telemetry_toolchain_old_perf_tests = [
+ 'dromaeo.domcoremodify', 'page_cycler_v2.intl_es_fr_pt-BR',
+ 'page_cycler_v2.intl_hi_ru', 'page_cycler_v2.intl_ja_zh',
+ 'page_cycler_v2.intl_ko_th_vi', 'page_cycler_v2.netsim.top_10',
+ 'page_cycler_v2.typical_25', 'robohornet_pro', 'spaceport',
+ 'tab_switching.top_10'
+]
+telemetry_toolchain_perf_tests = [
+ 'octane',
+ 'kraken',
+ 'speedometer',
+ 'dromaeo.domcoreattr',
+ 'dromaeo.domcoremodify',
+ 'smoothness.tough_webgl_cases',
+]
+graphics_perf_tests = [
+ 'graphics_GLBench',
+ 'graphics_GLMark2',
+ 'graphics_SanAngeles',
+ 'graphics_WebGLAquarium',
+ 'graphics_WebGLPerformance',
+]
+telemetry_crosbolt_perf_tests = [
+ 'octane',
+ 'kraken',
+ 'speedometer',
+ 'jetstream',
+ 'startup.cold.blank_page',
+ 'smoothness.top_25_smooth',
+]
+crosbolt_perf_tests = [
+ 'graphics_WebGLAquarium',
+ 'video_PlaybackPerf.h264',
+ 'video_PlaybackPerf.vp9',
+ 'video_WebRtcPerf',
+ 'BootPerfServerCrosPerf',
+ 'power_Resume',
+ 'video_PlaybackPerf.h264',
+ 'build_RootFilesystemSize',
+# 'cheets_AntutuTest',
+# 'cheets_PerfBootServer',
+# 'cheets_CandyCrushTest',
+# 'cheets_LinpackTest',
+]
+
+
+class ExperimentFactory(object):
+ """Factory class for building an Experiment, given an ExperimentFile as input.
+
+ This factory is currently hardcoded to produce an experiment for running
+ ChromeOS benchmarks, but the idea is that in the future, other types
+ of experiments could be produced.
+ """
+
+ def AppendBenchmarkSet(self, benchmarks, benchmark_list, test_args,
+ iterations, rm_chroot_tmp, perf_args, suite,
+ show_all_results, retries, run_local):
+ """Add all the tests in a set to the benchmarks list."""
+ for test_name in benchmark_list:
+ telemetry_benchmark = Benchmark(test_name, test_name, test_args,
+ iterations, rm_chroot_tmp, perf_args,
+ suite, show_all_results, retries,
+ run_local)
+ benchmarks.append(telemetry_benchmark)
+
+ def GetExperiment(self, experiment_file, working_directory, log_dir):
+ """Construct an experiment from an experiment file."""
+ global_settings = experiment_file.GetGlobalSettings()
+ experiment_name = global_settings.GetField('name')
+ board = global_settings.GetField('board')
+ remote = global_settings.GetField('remote')
+ # This is used to remove the ",' from the remote if user
+ # add them to the remote string.
+ new_remote = []
+ if remote:
+ for i in remote:
+ c = re.sub('["\']', '', i)
+ new_remote.append(c)
+ remote = new_remote
+ chromeos_root = global_settings.GetField('chromeos_root')
+ rm_chroot_tmp = global_settings.GetField('rm_chroot_tmp')
+ perf_args = global_settings.GetField('perf_args')
+ acquire_timeout = global_settings.GetField('acquire_timeout')
+ cache_dir = global_settings.GetField('cache_dir')
+ cache_only = global_settings.GetField('cache_only')
+ config.AddConfig('no_email', global_settings.GetField('no_email'))
+ share_cache = global_settings.GetField('share_cache')
+ results_dir = global_settings.GetField('results_dir')
+ use_file_locks = global_settings.GetField('use_file_locks')
+ locks_dir = global_settings.GetField('locks_dir')
+ # If we pass a blank locks_dir to the Experiment, it will use the AFE server
+ # lock mechanism. So if the user specified use_file_locks, but did not
+ # specify a locks dir, set the locks dir to the default locks dir in
+ # file_lock_machine.
+ if use_file_locks and not locks_dir:
+ locks_dir = file_lock_machine.Machine.LOCKS_DIR
+ chrome_src = global_settings.GetField('chrome_src')
+ show_all_results = global_settings.GetField('show_all_results')
+ log_level = global_settings.GetField('logging_level')
+ if log_level not in ('quiet', 'average', 'verbose'):
+ log_level = 'verbose'
+ # Default cache hit conditions. The image checksum in the cache and the
+ # computed checksum of the image must match. Also a cache file must exist.
+ cache_conditions = [
+ CacheConditions.CACHE_FILE_EXISTS, CacheConditions.CHECKSUMS_MATCH
+ ]
+ if global_settings.GetField('rerun_if_failed'):
+ cache_conditions.append(CacheConditions.RUN_SUCCEEDED)
+ if global_settings.GetField('rerun'):
+ cache_conditions.append(CacheConditions.FALSE)
+ if global_settings.GetField('same_machine'):
+ cache_conditions.append(CacheConditions.SAME_MACHINE_MATCH)
+ if global_settings.GetField('same_specs'):
+ cache_conditions.append(CacheConditions.MACHINES_MATCH)
+
+ # Construct benchmarks.
+ # Some fields are common with global settings. The values are
+ # inherited and/or merged with the global settings values.
+ benchmarks = []
+ all_benchmark_settings = experiment_file.GetSettings('benchmark')
+ for benchmark_settings in all_benchmark_settings:
+ benchmark_name = benchmark_settings.name
+ test_name = benchmark_settings.GetField('test_name')
+ if not test_name:
+ test_name = benchmark_name
+ test_args = benchmark_settings.GetField('test_args')
+ iterations = benchmark_settings.GetField('iterations')
+ suite = benchmark_settings.GetField('suite')
+ retries = benchmark_settings.GetField('retries')
+ run_local = benchmark_settings.GetField('run_local')
+
+ if suite == 'telemetry_Crosperf':
+ if test_name == 'all_perfv2':
+ self.AppendBenchmarkSet(benchmarks, telemetry_perfv2_tests, test_args,
+ iterations, rm_chroot_tmp, perf_args, suite,
+ show_all_results, retries, run_local)
+ elif test_name == 'all_pagecyclers':
+ self.AppendBenchmarkSet(benchmarks, telemetry_pagecycler_tests,
+ test_args, iterations, rm_chroot_tmp,
+ perf_args, suite, show_all_results, retries,
+ run_local)
+ elif test_name == 'all_toolchain_perf':
+ self.AppendBenchmarkSet(benchmarks, telemetry_toolchain_perf_tests,
+ test_args, iterations, rm_chroot_tmp,
+ perf_args, suite, show_all_results, retries,
+ run_local)
+ # Add non-telemetry toolchain-perf benchmarks:
+ benchmarks.append(
+ Benchmark(
+ 'graphics_WebGLAquarium',
+ 'graphics_WebGLAquarium',
+ '',
+ iterations,
+ rm_chroot_tmp,
+ perf_args,
+ '',
+ show_all_results,
+ retries,
+ run_local=False))
+ elif test_name == 'all_toolchain_perf_old':
+ self.AppendBenchmarkSet(benchmarks,
+ telemetry_toolchain_old_perf_tests, test_args,
+ iterations, rm_chroot_tmp, perf_args, suite,
+ show_all_results, retries, run_local)
+ else:
+ benchmark = Benchmark(test_name, test_name, test_args, iterations,
+ rm_chroot_tmp, perf_args, suite,
+ show_all_results, retries, run_local)
+ benchmarks.append(benchmark)
+ else:
+ if test_name == 'all_graphics_perf':
+ self.AppendBenchmarkSet(benchmarks,
+ graphics_perf_tests, '',
+ iterations, rm_chroot_tmp, perf_args, '',
+ show_all_results, retries, run_local=False)
+ elif test_name == 'all_crosbolt_perf':
+ self.AppendBenchmarkSet(benchmarks,
+ telemetry_crosbolt_perf_tests, test_args,
+ iterations, rm_chroot_tmp, perf_args,
+ 'telemetry_Crosperf', show_all_results,
+ retries, run_local)
+ self.AppendBenchmarkSet(benchmarks,
+ crosbolt_perf_tests, '',
+ iterations, rm_chroot_tmp, perf_args, '',
+ show_all_results, retries, run_local=False)
+ else:
+ # Add the single benchmark.
+ benchmark = Benchmark(
+ benchmark_name,
+ test_name,
+ test_args,
+ iterations,
+ rm_chroot_tmp,
+ perf_args,
+ suite,
+ show_all_results,
+ retries,
+ run_local=False)
+ benchmarks.append(benchmark)
+
+ if not benchmarks:
+ raise RuntimeError('No benchmarks specified')
+
+ # Construct labels.
+ # Some fields are common with global settings. The values are
+ # inherited and/or merged with the global settings values.
+ labels = []
+ all_label_settings = experiment_file.GetSettings('label')
+ all_remote = list(remote)
+ for label_settings in all_label_settings:
+ label_name = label_settings.name
+ image = label_settings.GetField('chromeos_image')
+ autotest_path = label_settings.GetField('autotest_path')
+ chromeos_root = label_settings.GetField('chromeos_root')
+ my_remote = label_settings.GetField('remote')
+ compiler = label_settings.GetField('compiler')
+ new_remote = []
+ if my_remote:
+ for i in my_remote:
+ c = re.sub('["\']', '', i)
+ new_remote.append(c)
+ my_remote = new_remote
+ if image == '':
+ build = label_settings.GetField('build')
+ if len(build) == 0:
+ raise RuntimeError("Can not have empty 'build' field!")
+ image, autotest_path = label_settings.GetXbuddyPath(build,
+ autotest_path,
+ board,
+ chromeos_root,
+ log_level)
+
+ cache_dir = label_settings.GetField('cache_dir')
+ chrome_src = label_settings.GetField('chrome_src')
+
+ # TODO(yunlian): We should consolidate code in machine_manager.py
+ # to derermine whether we are running from within google or not
+ if ('corp.google.com' in socket.gethostname() and
+ (not my_remote or my_remote == remote and
+ global_settings.GetField('board') != board)):
+ my_remote = self.GetDefaultRemotes(board)
+ if global_settings.GetField('same_machine') and len(my_remote) > 1:
+ raise RuntimeError('Only one remote is allowed when same_machine '
+ 'is turned on')
+ all_remote += my_remote
+ image_args = label_settings.GetField('image_args')
+ if test_flag.GetTestMode():
+ # pylint: disable=too-many-function-args
+ label = MockLabel(label_name, image, autotest_path, chromeos_root,
+ board, my_remote, image_args, cache_dir, cache_only,
+ log_level, compiler, chrome_src)
+ else:
+ label = Label(label_name, image, autotest_path, chromeos_root, board,
+ my_remote, image_args, cache_dir, cache_only, log_level,
+ compiler, chrome_src)
+ labels.append(label)
+
+ if not labels:
+ raise RuntimeError('No labels specified')
+
+ email = global_settings.GetField('email')
+ all_remote += list(set(my_remote))
+ all_remote = list(set(all_remote))
+ experiment = Experiment(experiment_name, all_remote, working_directory,
+ chromeos_root, cache_conditions, labels, benchmarks,
+ experiment_file.Canonicalize(), email,
+ acquire_timeout, log_dir, log_level, share_cache,
+ results_dir, locks_dir)
+
+ return experiment
+
+ def GetDefaultRemotes(self, board):
+ default_remotes_file = os.path.join(
+ os.path.dirname(__file__), 'default_remotes')
+ try:
+ with open(default_remotes_file) as f:
+ for line in f:
+ key, v = line.split(':')
+ if key.strip() == board:
+ remotes = v.strip().split()
+ if remotes:
+ return remotes
+ else:
+ raise RuntimeError('There is no remote for {0}'.format(board))
+ except IOError:
+ # TODO: rethrow instead of throwing different exception.
+ raise RuntimeError('IOError while reading file {0}'
+ .format(default_remotes_file))
+ else:
+ raise RuntimeError('There is not remote for {0}'.format(board))