experiment_runner.py revision f81680c018729fd4499e1e200d04b48c4b90127c
1#!/usr/bin/python
2
3# Copyright 2011 Google Inc. All Rights Reserved.
4
5"""The experiment runner module."""
6import getpass
7import os
8import time
9
10from utils import command_executer
11from utils import logger
12from utils.email_sender import EmailSender
13from utils.file_utils import FileUtils
14
15import config
16from experiment_status import ExperimentStatus
17from results_report import HTMLResultsReport
18from results_report import TextResultsReport
19
20
21class ExperimentRunner(object):
22  """ExperimentRunner Class."""
23
24  STATUS_TIME_DELAY = 30
25  THREAD_MONITOR_DELAY = 2
26
27  def __init__(self, experiment):
28    self._experiment = experiment
29    self.l = logger.GetLogger(experiment.log_dir)
30    self._ce = command_executer.GetCommandExecuter(self.l)
31    self._terminated = False
32
33  def _Run(self, experiment):
34    status = ExperimentStatus(experiment)
35    experiment.Run()
36    last_status_time = 0
37    try:
38      while not experiment.IsComplete():
39        if last_status_time + self.STATUS_TIME_DELAY < time.time():
40          last_status_time = time.time()
41          border = "=============================="
42          self.l.LogOutput(border)
43          self.l.LogOutput(status.GetProgressString())
44          self.l.LogOutput(status.GetStatusString())
45          logger.GetLogger().LogOutput(border)
46        time.sleep(self.THREAD_MONITOR_DELAY)
47    except KeyboardInterrupt:
48      self._terminated = True
49      self.l.LogError("Ctrl-c pressed. Cleaning up...")
50      experiment.Terminate()
51
52  def _PrintTable(self, experiment):
53    self.l.LogOutput(TextResultsReport(experiment).GetReport())
54
55  def _Email(self, experiment):
56    # Only email by default if a new run was completed.
57    send_mail = False
58    for benchmark_run in experiment.benchmark_runs:
59      if not benchmark_run.cache_hit:
60        send_mail = True
61        break
62    if (not send_mail and not experiment.email_to
63        or config.GetConfig("no_email")):
64      return
65
66    label_names = []
67    for label in experiment.labels:
68      label_names.append(label.name)
69    subject = "%s: %s" % (experiment.name, " vs. ".join(label_names))
70
71    text_report = TextResultsReport(experiment, True).GetReport()
72    text_report = "<pre style='font-size: 13px'>%s</pre>" % text_report
73    html_report = HTMLResultsReport(experiment).GetReport()
74    attachment = EmailSender.Attachment("report.html", html_report)
75    email_to = [getpass.getuser()] + experiment.email_to
76    EmailSender().SendEmail(email_to,
77                            subject,
78                            text_report,
79                            attachments=[attachment],
80                            msg_type="html")
81
82  def _StoreResults (self, experiment):
83    if self._terminated:
84      return
85    results_directory = experiment.results_directory
86    FileUtils().RmDir(results_directory)
87    FileUtils().MkDirP(results_directory)
88    self.l.LogOutput("Storing experiment file.")
89    experiment_file_path = os.path.join(results_directory,
90                                        "experiment.exp")
91    FileUtils().WriteFile(experiment_file_path, experiment.experiment_file)
92
93    self.l.LogOutput("Storing results report.")
94    results_table_path = os.path.join(results_directory, "results.html")
95    report = HTMLResultsReport(experiment).GetReport()
96    FileUtils().WriteFile(results_table_path, report)
97
98    self.l.LogOutput("Storing results of each benchmark run.")
99    for benchmark_run in experiment.benchmark_runs:
100      if benchmark_run.result:
101        benchmark_run_name = filter(str.isalnum, benchmark_run.name)
102        benchmark_run_path = os.path.join(results_directory,
103                                          benchmark_run_name)
104        benchmark_run.result.CopyResultsTo(benchmark_run_path)
105        benchmark_run.result.CleanUp(benchmark_run.benchmark.rm_chroot_tmp)
106
107  def Run(self):
108    self._Run(self._experiment)
109    self._PrintTable(self._experiment)
110    if not self._terminated:
111      self._StoreResults(self._experiment)
112      self._Email(self._experiment)
113
114
115class MockExperimentRunner(ExperimentRunner):
116  """Mocked ExperimentRunner for testing."""
117
118  def __init__(self, experiment):
119    super(MockExperimentRunner, self).__init__(experiment)
120
121  def _Run(self, experiment):
122    self.l.LogOutput("Would run the following experiment: '%s'." %
123                     experiment.name)
124
125  def _PrintTable(self, experiment):
126    self.l.LogOutput("Would print the experiment table.")
127
128  def _Email(self, experiment):
129    self.l.LogOutput("Would send result email.")
130
131  def _StoreResults(self, experiment):
132    self.l.LogOutput("Would store the results.")
133