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