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