experiment.py revision e5bc63bbed4e001b080c4ce0b18c5c78900d4786
1#!/usr/bin/python 2 3# Copyright (c) 2013 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 experiment setting module.""" 8 9import os 10import time 11 12import afe_lock_machine 13 14from utils import logger 15from utils import misc 16 17from benchmark_run import BenchmarkRun 18from machine_manager import MachineManager 19from machine_manager import MockMachineManager 20import test_flag 21 22 23class Experiment(object): 24 """Class representing an Experiment to be run.""" 25 26 def __init__(self, name, remote, working_directory, 27 chromeos_root, cache_conditions, labels, benchmarks, 28 experiment_file, email_to, acquire_timeout, log_dir, 29 log_level, share_cache, results_directory, locks_directory): 30 self.name = name 31 self.working_directory = working_directory 32 self.remote = remote 33 self.chromeos_root = chromeos_root 34 self.cache_conditions = cache_conditions 35 self.experiment_file = experiment_file 36 self.email_to = email_to 37 if not results_directory: 38 self.results_directory = os.path.join(self.working_directory, 39 self.name + "_results") 40 else: 41 self.results_directory = misc.CanonicalizePath(results_directory) 42 self.log_dir = log_dir 43 self.log_level = log_level 44 self.labels = labels 45 self.benchmarks = benchmarks 46 self.num_complete = 0 47 self.num_run_complete = 0 48 self.share_cache = share_cache 49 50 # We need one chromeos_root to run the benchmarks in, but it doesn't 51 # matter where it is, unless the ABIs are different. 52 if not chromeos_root: 53 for label in self.labels: 54 if label.chromeos_root: 55 chromeos_root = label.chromeos_root 56 if not chromeos_root: 57 raise Exception("No chromeos_root given and could not determine one from " 58 "the image path.") 59 60 # This is a local directory, where the machine manager will keep track of 61 # which machines are available for which benchmark run. The assumption is 62 # that all of the machines have been globally locked for this experiment, 63 # to keep other people/experiments from accessing them, but we still need the 64 # local locks directory to keep two or more benchmark runs within the same 65 # experiment from trying to use the same machine at the same time. 66 local_locks_directory = os.path.join(self.working_directory, 67 "local_locks") 68 if test_flag.GetTestMode(): 69 self.machine_manager = MockMachineManager(chromeos_root, acquire_timeout, 70 log_level, locks_directory) 71 else: 72 self.machine_manager = MachineManager(chromeos_root, acquire_timeout, 73 log_level, local_locks_directory) 74 self.l = logger.GetLogger(log_dir) 75 76 for machine in remote: 77 self.machine_manager.AddMachine(machine) 78 for label in labels: 79 self.machine_manager.ComputeCommonCheckSum(label) 80 self.machine_manager.ComputeCommonCheckSumString(label) 81 82 self.start_time = None 83 self.benchmark_runs = self._GenerateBenchmarkRuns() 84 85 def _GenerateBenchmarkRuns(self): 86 """Generate benchmark runs from labels and benchmark defintions.""" 87 benchmark_runs = [] 88 for label in self.labels: 89 for benchmark in self.benchmarks: 90 for iteration in range(1, benchmark.iterations + 1): 91 92 benchmark_run_name = "%s: %s (%s)" % (label.name, benchmark.name, 93 iteration) 94 full_name = "%s_%s_%s" % (label.name, benchmark.name, iteration) 95 logger_to_use = logger.Logger(self.log_dir, 96 "run.%s" % (full_name), 97 True) 98 benchmark_run = BenchmarkRun(benchmark_run_name, 99 benchmark, 100 label, 101 iteration, 102 self.cache_conditions, 103 self.machine_manager, 104 logger_to_use, 105 self.log_level, 106 self.share_cache) 107 108 benchmark_runs.append(benchmark_run) 109 return benchmark_runs 110 111 def Build(self): 112 pass 113 114 def Terminate(self): 115 for t in self.benchmark_runs: 116 if t.isAlive(): 117 self.l.LogError("Terminating run: '%s'." % t.name) 118 t.Terminate() 119 120 def IsComplete(self): 121 if self.active_threads: 122 for t in self.active_threads: 123 if t.isAlive(): 124 t.join(0) 125 if not t.isAlive(): 126 self.num_complete += 1 127 if not t.cache_hit: 128 self.num_run_complete += 1 129 self.active_threads.remove(t) 130 return False 131 return True 132 133 def Run(self): 134 self.start_time = time.time() 135 self.active_threads = [] 136 for benchmark_run in self.benchmark_runs: 137 # Set threads to daemon so program exits when ctrl-c is pressed. 138 benchmark_run.daemon = True 139 benchmark_run.start() 140 self.active_threads.append(benchmark_run) 141 142 def SetCacheConditions(self, cache_conditions): 143 for benchmark_run in self.benchmark_runs: 144 benchmark_run.SetCacheConditions(cache_conditions) 145 146 def Cleanup(self): 147 """Make sure all machines are unlocked.""" 148 all_machines = self.remote 149 for l in self.labels: 150 all_machines += l.remote 151 lock_mgr = afe_lock_machine.AFELockManager(all_machines, "", 152 self.labels[0].chromeos_root, None) 153 machine_states = lock_mgr.GetMachineStates("unlock") 154 for k, state in machine_states.iteritems(): 155 if state["locked"]: 156 lock_mgr.UpdateLockInAFE(False, k) 157