benchmark_run.py revision f81680c018729fd4499e1e200d04b48c4b90127c
1#!/usr/bin/python 2 3# Copyright 2011 Google Inc. All Rights Reserved. 4 5import datetime 6import os 7import threading 8import time 9import traceback 10 11from utils import command_executer 12from utils import timeline 13 14from autotest_runner import AutotestRunner 15from results_cache import Result 16from results_cache import ResultsCache 17 18STATUS_FAILED = "FAILED" 19STATUS_SUCCEEDED = "SUCCEEDED" 20STATUS_IMAGING = "IMAGING" 21STATUS_RUNNING = "RUNNING" 22STATUS_WAITING = "WAITING" 23STATUS_PENDING = "PENDING" 24 25 26class BenchmarkRun(threading.Thread): 27 def __init__(self, name, benchmark, 28 label, 29 iteration, 30 cache_conditions, 31 machine_manager, 32 logger_to_use, 33 share_users): 34 threading.Thread.__init__(self) 35 self.name = name 36 self._logger = logger_to_use 37 self.benchmark = benchmark 38 self.iteration = iteration 39 self.label = label 40 self.result = None 41 self.terminated = False 42 self.retval = None 43 self.run_completed = False 44 self.machine_manager = machine_manager 45 self.cache = ResultsCache() 46 self.autotest_runner = AutotestRunner(self._logger) 47 self.machine = None 48 self.cache_conditions = cache_conditions 49 self.runs_complete = 0 50 self.cache_hit = False 51 self.failure_reason = "" 52 self.autotest_args = "%s %s" % (benchmark.autotest_args, 53 self._GetExtraAutotestArgs()) 54 self._ce = command_executer.GetCommandExecuter(self._logger) 55 self.timeline = timeline.Timeline() 56 self.timeline.Record(STATUS_PENDING) 57 self.share_users = share_users 58 59 def run(self): 60 try: 61 # Just use the first machine for running the cached version, 62 # without locking it. 63 self.cache.Init(self.label.chromeos_image, 64 self.label.chromeos_root, 65 self.benchmark.autotest_name, 66 self.iteration, 67 self.autotest_args, 68 self.machine_manager, 69 self.label.board, 70 self.cache_conditions, 71 self._logger, 72 self.label, 73 self.share_users 74 ) 75 76 self.result = self.cache.ReadResult() 77 self.cache_hit = (self.result is not None) 78 79 if self.result: 80 self._logger.LogOutput("%s: Cache hit." % self.name) 81 self._logger.LogOutput(self.result.out, print_to_console=False) 82 self._logger.LogError(self.result.err, print_to_console=False) 83 84 else: 85 self._logger.LogOutput("%s: No cache hit." % self.name) 86 self.timeline.Record(STATUS_WAITING) 87 # Try to acquire a machine now. 88 self.machine = self.AcquireMachine() 89 self.cache.remote = self.machine.name 90 self.result = self.RunTest(self.machine) 91 self.cache.StoreResult(self.result) 92 93 if self.terminated: 94 return 95 96 if not self.result.retval: 97 self.timeline.Record(STATUS_SUCCEEDED) 98 else: 99 if self.timeline.GetLastEvent() != STATUS_FAILED: 100 self.failure_reason = "Return value of autotest was non-zero." 101 self.timeline.Record(STATUS_FAILED) 102 103 except Exception, e: 104 self._logger.LogError("Benchmark run: '%s' failed: %s" % (self.name, e)) 105 traceback.print_exc() 106 if self.timeline.GetLastEvent() != STATUS_FAILED: 107 self.timeline.Record(STATUS_FAILED) 108 self.failure_reason = str(e) 109 finally: 110 if self.machine: 111 self._logger.LogOutput("Releasing machine: %s" % self.machine.name) 112 self.machine_manager.ReleaseMachine(self.machine) 113 self._logger.LogOutput("Released machine: %s" % self.machine.name) 114 115 def Terminate(self): 116 self.terminated = True 117 self.autotest_runner.Terminate() 118 if self.timeline.GetLastEvent() != STATUS_FAILED: 119 self.timeline.Record(STATUS_FAILED) 120 self.failure_reason = "Thread terminated." 121 122 def AcquireMachine(self): 123 while True: 124 if self.terminated: 125 raise Exception("Thread terminated while trying to acquire machine.") 126 machine = self.machine_manager.AcquireMachine(self.label.chromeos_image, 127 self.label) 128 129 if machine: 130 self._logger.LogOutput("%s: Machine %s acquired at %s" % 131 (self.name, 132 machine.name, 133 datetime.datetime.now())) 134 break 135 else: 136 sleep_duration = 10 137 time.sleep(sleep_duration) 138 return machine 139 140 def _GetExtraAutotestArgs(self): 141 if self.benchmark.perf_args: 142 perf_args_list = self.benchmark.perf_args.split(" ") 143 perf_args_list = [perf_args_list[0]] + ["-a"] + perf_args_list[1:] 144 perf_args = " ".join(perf_args_list) 145 if not perf_args_list[0] in ["record", "stat"]: 146 raise Exception("perf_args must start with either record or stat") 147 extra_autotest_args = ["--profiler=custom_perf", 148 ("--profiler_args='perf_options=\"%s\"'" % 149 perf_args)] 150 return " ".join(extra_autotest_args) 151 else: 152 return "" 153 154 def RunTest(self, machine): 155 self.timeline.Record(STATUS_IMAGING) 156 self.machine_manager.ImageMachine(machine, 157 self.label) 158 self.timeline.Record(STATUS_RUNNING) 159 [retval, out, err] = self.autotest_runner.Run(machine.name, 160 self.label.chromeos_root, 161 self.label.board, 162 self.benchmark.autotest_name, 163 self.autotest_args) 164 self.run_completed = True 165 166 return Result.CreateFromRun(self._logger, 167 self.label.chromeos_root, 168 self.label.board, 169 self.label.name, 170 out, 171 err, 172 retval) 173 174 def SetCacheConditions(self, cache_conditions): 175 self.cache_conditions = cache_conditions 176 177 178class MockBenchmarkRun(BenchmarkRun): 179 """Inherited from BenchmarkRun, just overide RunTest for testing.""" 180 181 def RunTest(self, machine): 182 """Remove Result.CreateFromRun for testing.""" 183 self.timeline.Record(STATUS_IMAGING) 184 self.machine_manager.ImageMachine(machine, 185 self.label) 186 self.timeline.Record(STATUS_RUNNING) 187 [retval, out, err] = self.autotest_runner.Run(machine.name, 188 self.label.chromeos_root, 189 self.label.board, 190 self.benchmark.autotest_name, 191 self.autotest_args) 192 self.run_completed = True 193 rr = Result("Results placed in /tmp/test", "", 0) 194 rr.out = out 195 rr.err = err 196 rr.retval = retval 197 return rr 198 199