blob: 7fa34c3f25a960f7eb22a02867a92ce78275d7c0 [file] [log] [blame]
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -08001#!/usr/bin/python
2
Yunlian Jiang00cc30e2013-03-28 13:23:57 -07003# 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.
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -08006
Ahmad Sharif4467f002012-12-20 12:09:49 -08007"""The experiment setting module."""
8
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -08009import os
10import time
Ahmad Sharif4467f002012-12-20 12:09:49 -080011
cmticee5bc63b2015-05-27 16:59:37 -070012import afe_lock_machine
Han Shenba649282015-08-05 17:19:55 -070013from threading import Lock
cmticee5bc63b2015-05-27 16:59:37 -070014
Ahmad Sharif4467f002012-12-20 12:09:49 -080015from utils import logger
Yunlian Jiang00cc30e2013-03-28 13:23:57 -070016from utils import misc
Ahmad Sharif4467f002012-12-20 12:09:49 -080017
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080018from benchmark_run import BenchmarkRun
19from machine_manager import MachineManager
Ahmad Sharif4467f002012-12-20 12:09:49 -080020from machine_manager import MockMachineManager
Ahmad Sharif4467f002012-12-20 12:09:49 -080021import test_flag
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080022
23
24class Experiment(object):
25 """Class representing an Experiment to be run."""
26
Luis Lozanof81680c2013-03-15 14:44:13 -070027 def __init__(self, name, remote, working_directory,
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080028 chromeos_root, cache_conditions, labels, benchmarks,
Luis Lozanof81680c2013-03-15 14:44:13 -070029 experiment_file, email_to, acquire_timeout, log_dir,
cmtice5c09fc22015-04-22 09:25:53 -070030 log_level, share_cache, results_directory, locks_directory):
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080031 self.name = name
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080032 self.working_directory = working_directory
33 self.remote = remote
34 self.chromeos_root = chromeos_root
35 self.cache_conditions = cache_conditions
36 self.experiment_file = experiment_file
Ahmad Shariff395c262012-10-09 17:48:09 -070037 self.email_to = email_to
Yunlian Jiang00cc30e2013-03-28 13:23:57 -070038 if not results_directory:
39 self.results_directory = os.path.join(self.working_directory,
40 self.name + "_results")
41 else:
42 self.results_directory = misc.CanonicalizePath(results_directory)
Luis Lozanof81680c2013-03-15 14:44:13 -070043 self.log_dir = log_dir
cmtice13909242014-03-11 13:38:07 -070044 self.log_level = log_level
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080045 self.labels = labels
46 self.benchmarks = benchmarks
47 self.num_complete = 0
Ahmad Sharif4467f002012-12-20 12:09:49 -080048 self.num_run_complete = 0
cmtice1a224362014-10-16 15:49:56 -070049 self.share_cache = share_cache
cmtice517dc982015-06-12 12:22:32 -070050 # If locks_directory (self.lock_dir) not blank, we will use the file
51 # locking mechanism; if it is blank then we will use the AFE server
52 # locking mechanism.
53 self.locks_dir = locks_directory
cmticef3eb8032015-07-27 13:55:52 -070054 self.locked_machines = []
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080055
56 # We need one chromeos_root to run the benchmarks in, but it doesn't
57 # matter where it is, unless the ABIs are different.
58 if not chromeos_root:
59 for label in self.labels:
60 if label.chromeos_root:
61 chromeos_root = label.chromeos_root
62 if not chromeos_root:
63 raise Exception("No chromeos_root given and could not determine one from "
64 "the image path.")
65
Ahmad Sharif4467f002012-12-20 12:09:49 -080066 if test_flag.GetTestMode():
cmtice13909242014-03-11 13:38:07 -070067 self.machine_manager = MockMachineManager(chromeos_root, acquire_timeout,
cmticed96e4572015-05-19 16:19:25 -070068 log_level, locks_directory)
Ahmad Sharif4467f002012-12-20 12:09:49 -080069 else:
cmtice13909242014-03-11 13:38:07 -070070 self.machine_manager = MachineManager(chromeos_root, acquire_timeout,
cmtice517dc982015-06-12 12:22:32 -070071 log_level, locks_directory)
Luis Lozanof81680c2013-03-15 14:44:13 -070072 self.l = logger.GetLogger(log_dir)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080073
Han Shenf9b50352015-09-17 11:26:22 -070074 for machine in self.remote:
75 # machine_manager.AddMachine only adds reachable machines.
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080076 self.machine_manager.AddMachine(machine)
Han Shenf9b50352015-09-17 11:26:22 -070077 # Now machine_manager._all_machines contains a list of reachable
78 # machines. This is a subset of self.remote. We make both lists the same.
79 self.remote = [m.name for m in self.machine_manager._all_machines]
80
Ahmad Sharif4467f002012-12-20 12:09:49 -080081 for label in labels:
Han Shenf9b50352015-09-17 11:26:22 -070082 # We filter out label remotes that are not reachable (not in
83 # self.remote). So each label.remote is a sublist of experiment.remote.
84 label.remote = filter(lambda x: x in self.remote, label.remote)
Ahmad Sharif4467f002012-12-20 12:09:49 -080085 self.machine_manager.ComputeCommonCheckSum(label)
86 self.machine_manager.ComputeCommonCheckSumString(label)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080087
88 self.start_time = None
89 self.benchmark_runs = self._GenerateBenchmarkRuns()
90
Han Shenba649282015-08-05 17:19:55 -070091 self._schedv2 = None
92 self._internal_counter_lock = Lock()
93
94 def set_schedv2(self, schedv2):
95 self._schedv2 = schedv2
96
97 def schedv2(self):
98 return self._schedv2
99
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800100 def _GenerateBenchmarkRuns(self):
101 """Generate benchmark runs from labels and benchmark defintions."""
102 benchmark_runs = []
103 for label in self.labels:
104 for benchmark in self.benchmarks:
105 for iteration in range(1, benchmark.iterations + 1):
106
107 benchmark_run_name = "%s: %s (%s)" % (label.name, benchmark.name,
108 iteration)
109 full_name = "%s_%s_%s" % (label.name, benchmark.name, iteration)
Luis Lozanof81680c2013-03-15 14:44:13 -0700110 logger_to_use = logger.Logger(self.log_dir,
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800111 "run.%s" % (full_name),
cmtice77892942014-03-18 13:47:17 -0700112 True)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800113 benchmark_run = BenchmarkRun(benchmark_run_name,
Ahmad Sharif4467f002012-12-20 12:09:49 -0800114 benchmark,
115 label,
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800116 iteration,
117 self.cache_conditions,
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800118 self.machine_manager,
Luis Lozanof81680c2013-03-15 14:44:13 -0700119 logger_to_use,
cmtice13909242014-03-11 13:38:07 -0700120 self.log_level,
cmtice1a224362014-10-16 15:49:56 -0700121 self.share_cache)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800122
123 benchmark_runs.append(benchmark_run)
124 return benchmark_runs
125
126 def Build(self):
127 pass
128
129 def Terminate(self):
Han Shenba649282015-08-05 17:19:55 -0700130 if self._schedv2 is not None:
131 self._schedv2.terminate()
132 else:
133 for t in self.benchmark_runs:
134 if t.isAlive():
135 self.l.LogError("Terminating run: '%s'." % t.name)
136 t.Terminate()
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800137
138 def IsComplete(self):
Han Shenba649282015-08-05 17:19:55 -0700139 if self._schedv2:
140 return self._schedv2.is_complete()
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800141 if self.active_threads:
142 for t in self.active_threads:
143 if t.isAlive():
144 t.join(0)
145 if not t.isAlive():
146 self.num_complete += 1
Ahmad Sharif4467f002012-12-20 12:09:49 -0800147 if not t.cache_hit:
148 self.num_run_complete += 1
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800149 self.active_threads.remove(t)
150 return False
151 return True
152
Han Shenba649282015-08-05 17:19:55 -0700153 def BenchmarkRunFinished(self, br):
154 """Update internal counters after br finishes.
155
156 Note this is only used by schedv2 and is called by multiple threads.
157 Never throw any exception here.
158 """
159
160 assert self._schedv2 is not None
161 with self._internal_counter_lock:
162 self.num_complete += 1
163 if not br.cache_hit:
164 self.num_run_complete += 1
165
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800166 def Run(self):
167 self.start_time = time.time()
Han Shenba649282015-08-05 17:19:55 -0700168 if self._schedv2 is not None:
169 self._schedv2.run_sched()
170 else:
171 self.active_threads = []
172 for benchmark_run in self.benchmark_runs:
173 # Set threads to daemon so program exits when ctrl-c is pressed.
174 benchmark_run.daemon = True
175 benchmark_run.start()
176 self.active_threads.append(benchmark_run)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800177
178 def SetCacheConditions(self, cache_conditions):
179 for benchmark_run in self.benchmark_runs:
180 benchmark_run.SetCacheConditions(cache_conditions)
181
182 def Cleanup(self):
cmticee5bc63b2015-05-27 16:59:37 -0700183 """Make sure all machines are unlocked."""
cmtice517dc982015-06-12 12:22:32 -0700184 if self.locks_dir:
185 # We are using the file locks mechanism, so call machine_manager.Cleanup
186 # to unlock everything.
187 self.machine_manager.Cleanup()
188 else:
cmticef3eb8032015-07-27 13:55:52 -0700189 all_machines = self.locked_machines
190 if not all_machines:
191 return
192
193 # If we locked any machines earlier, make sure we unlock them now.
cmtice517dc982015-06-12 12:22:32 -0700194 lock_mgr = afe_lock_machine.AFELockManager(all_machines, "",
195 self.labels[0].chromeos_root,
196 None)
197 machine_states = lock_mgr.GetMachineStates("unlock")
198 for k, state in machine_states.iteritems():
199 if state["locked"]:
200 lock_mgr.UpdateLockInAFE(False, k)