blob: 59e932f61cd3b058fe46cfd71fe7f7102458b69e [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
74 for machine in remote:
75 self.machine_manager.AddMachine(machine)
Ahmad Sharif4467f002012-12-20 12:09:49 -080076 for label in labels:
77 self.machine_manager.ComputeCommonCheckSum(label)
78 self.machine_manager.ComputeCommonCheckSumString(label)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080079
80 self.start_time = None
81 self.benchmark_runs = self._GenerateBenchmarkRuns()
82
Han Shenba649282015-08-05 17:19:55 -070083 self._schedv2 = None
84 self._internal_counter_lock = Lock()
85
86 def set_schedv2(self, schedv2):
87 self._schedv2 = schedv2
88
89 def schedv2(self):
90 return self._schedv2
91
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -080092 def _GenerateBenchmarkRuns(self):
93 """Generate benchmark runs from labels and benchmark defintions."""
94 benchmark_runs = []
95 for label in self.labels:
96 for benchmark in self.benchmarks:
97 for iteration in range(1, benchmark.iterations + 1):
98
99 benchmark_run_name = "%s: %s (%s)" % (label.name, benchmark.name,
100 iteration)
101 full_name = "%s_%s_%s" % (label.name, benchmark.name, iteration)
Luis Lozanof81680c2013-03-15 14:44:13 -0700102 logger_to_use = logger.Logger(self.log_dir,
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800103 "run.%s" % (full_name),
cmtice77892942014-03-18 13:47:17 -0700104 True)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800105 benchmark_run = BenchmarkRun(benchmark_run_name,
Ahmad Sharif4467f002012-12-20 12:09:49 -0800106 benchmark,
107 label,
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800108 iteration,
109 self.cache_conditions,
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800110 self.machine_manager,
Luis Lozanof81680c2013-03-15 14:44:13 -0700111 logger_to_use,
cmtice13909242014-03-11 13:38:07 -0700112 self.log_level,
cmtice1a224362014-10-16 15:49:56 -0700113 self.share_cache)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800114
115 benchmark_runs.append(benchmark_run)
116 return benchmark_runs
117
118 def Build(self):
119 pass
120
121 def Terminate(self):
Han Shenba649282015-08-05 17:19:55 -0700122 if self._schedv2 is not None:
123 self._schedv2.terminate()
124 else:
125 for t in self.benchmark_runs:
126 if t.isAlive():
127 self.l.LogError("Terminating run: '%s'." % t.name)
128 t.Terminate()
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800129
130 def IsComplete(self):
Han Shenba649282015-08-05 17:19:55 -0700131 if self._schedv2:
132 return self._schedv2.is_complete()
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800133 if self.active_threads:
134 for t in self.active_threads:
135 if t.isAlive():
136 t.join(0)
137 if not t.isAlive():
138 self.num_complete += 1
Ahmad Sharif4467f002012-12-20 12:09:49 -0800139 if not t.cache_hit:
140 self.num_run_complete += 1
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800141 self.active_threads.remove(t)
142 return False
143 return True
144
Han Shenba649282015-08-05 17:19:55 -0700145 def BenchmarkRunFinished(self, br):
146 """Update internal counters after br finishes.
147
148 Note this is only used by schedv2 and is called by multiple threads.
149 Never throw any exception here.
150 """
151
152 assert self._schedv2 is not None
153 with self._internal_counter_lock:
154 self.num_complete += 1
155 if not br.cache_hit:
156 self.num_run_complete += 1
157
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800158 def Run(self):
159 self.start_time = time.time()
Han Shenba649282015-08-05 17:19:55 -0700160 if self._schedv2 is not None:
161 self._schedv2.run_sched()
162 else:
163 self.active_threads = []
164 for benchmark_run in self.benchmark_runs:
165 # Set threads to daemon so program exits when ctrl-c is pressed.
166 benchmark_run.daemon = True
167 benchmark_run.start()
168 self.active_threads.append(benchmark_run)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800169
170 def SetCacheConditions(self, cache_conditions):
171 for benchmark_run in self.benchmark_runs:
172 benchmark_run.SetCacheConditions(cache_conditions)
173
174 def Cleanup(self):
cmticee5bc63b2015-05-27 16:59:37 -0700175 """Make sure all machines are unlocked."""
cmtice517dc982015-06-12 12:22:32 -0700176 if self.locks_dir:
177 # We are using the file locks mechanism, so call machine_manager.Cleanup
178 # to unlock everything.
179 self.machine_manager.Cleanup()
180 else:
cmticef3eb8032015-07-27 13:55:52 -0700181 all_machines = self.locked_machines
182 if not all_machines:
183 return
184
185 # If we locked any machines earlier, make sure we unlock them now.
cmtice517dc982015-06-12 12:22:32 -0700186 lock_mgr = afe_lock_machine.AFELockManager(all_machines, "",
187 self.labels[0].chromeos_root,
188 None)
189 machine_states = lock_mgr.GetMachineStates("unlock")
190 for k, state in machine_states.iteritems():
191 if state["locked"]:
192 lock_mgr.UpdateLockInAFE(False, k)