aboutsummaryrefslogtreecommitdiffstats
path: root/experiment/experiment.py
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2012-09-16 20:46:19 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2012-09-16 20:46:19 -0400
commitbdb33621ac67b2cd9fadf3f3b006419ebb16a713 (patch)
tree8918b5dbc6db8a73c275e445153c7ea42857210b /experiment/experiment.py
parentfd92ecb5a642eeae6c54d3cca1508fc4c4cb6a87 (diff)
Created run_exps.py script.
Currently poorly documented.
Diffstat (limited to 'experiment/experiment.py')
-rw-r--r--experiment/experiment.py153
1 files changed, 153 insertions, 0 deletions
diff --git a/experiment/experiment.py b/experiment/experiment.py
new file mode 100644
index 0000000..29e6bd7
--- /dev/null
+++ b/experiment/experiment.py
@@ -0,0 +1,153 @@
1import os
2import time
3import litmus_util
4from operator import methodcaller
5from tracer import SchedTracer, LogTracer, PerfTracer, LinuxTracer, OverheadTracer
6
7class ExperimentException(Exception):
8 """Used to indicate when there are problems with an experiment."""
9 def __init__(self, name):
10 self.name = name
11
12
13class ExperimentDone(ExperimentException):
14 """Raised when an experiment looks like it's been run already."""
15 def __str__(self):
16 return "Experiment finished already: %d" % self.name
17
18
19class ExperimentInterrupted(ExperimentException):
20 """Raised when an experiment appears to be interrupted (partial results)."""
21 def __str__(self):
22 return "Experiment was interrupted in progress: %d" % self.name
23
24
25class ExperimentFailed(ExperimentException):
26 def __str__(self):
27 return "Experiment failed during execution: %d" % self.name
28
29
30class Experiment(object):
31 """Execute one task-set and save the results. Experiments have unique IDs."""
32
33 def __init__(self, name, scheduler, working_dir, finished_dir, proc_entries, executables):
34 """Run an experiment, optionally wrapped in tracing."""
35
36 self.name = name
37 self.scheduler = scheduler
38 self.working_dir = working_dir
39 self.finished_dir = finished_dir
40 self.proc_entries = proc_entries
41 self.executables = executables
42
43 self.__make_dirs()
44 self.__assign_executable_cwds()
45
46 self.tracers = []
47 if SchedTracer.enabled():
48 self.tracers.append( SchedTracer(working_dir) )
49 if LinuxTracer.enabled():
50 self.tracers.append( LinuxTracer(working_dir) )
51 if LogTracer.enabled():
52 self.tracers.append( LogTracer(working_dir) )
53 if PerfTracer.enabled():
54 self.tracers.append( PerfTracer(working_dir) )
55
56 # Overhead trace must be handled seperately, see __run_tasks
57 if OverheadTracer.enabled():
58 self.overhead_trace = OverheadTracer(working_dir)
59 else:
60 self.overhead_trace = None
61
62 def __make_dirs(self):
63 if os.path.exists(self.finished_dir):
64 raise ExperimentDone(self.name)
65 if os.path.exists(self.working_dir):
66 raise ExperimentInterrupted(self.name)
67
68 os.mkdir(self.working_dir)
69
70 def __assign_executable_cwds(self):
71 def assign_cwd(executable):
72 executable.cwd = self.working_dir
73 map(assign_cwd, self.executables)
74
75 def __run_tasks(self):
76 exec_pause = 0.3
77 self.log("Starting the program in ({0} seconds)".format(
78 len(self.executables) * exec_pause))
79 for e in self.executables:
80 e.execute()
81 time.sleep(exec_pause)
82
83 sleep_time = 2
84 self.log("Sleeping for %d seconds before release" % sleep_time)
85 time.sleep(sleep_time)
86
87 # Overhead tracer must be started right after release or overhead
88 # measurements will be full of irrelevant records
89 if self.overhead_trace:
90 self.log("Starting overhead trace")
91 self.overhead_trace.start_tracing()
92
93 released = litmus_util.release_tasks()
94
95 ret = True
96 if released != len(self.executables):
97 self.log("Failed to release %d tasks! Re-releasing and killing".format(
98 len(self.experiments) - released))
99
100 time.sleep(10)
101 litmus_util.release_tasks()
102
103 time.sleep(20)
104 map(methodcaller('kill'), self.executables)
105
106 ret = False
107
108 self.log("Waiting for program to finish...")
109 map(methodcaller('wait'), self.executables)
110
111 # And it must be stopped here for the same reason
112 if self.overhead_trace:
113 self.log("Stopping overhead trace")
114 self.overhead_trace.stop_tracing()
115
116 if not ret:
117 raise ExperimentFailed(self.name)
118
119 def __save_results(self):
120 os.rename(self.working_dir, self.finished_dir)
121
122 def log(self, msg):
123 print "[Exp %s]: %s" % (self.name, msg)
124
125 def run_exp(self):
126 self.setup()
127 self.__run_tasks()
128 self.teardown()
129
130 def setup(self):
131 self.log("Switching to %s" % self.scheduler)
132 litmus_util.switch_scheduler(self.scheduler)
133
134 self.log("Writing %d proc entries" % len(self.proc_entries))
135 map(methodcaller('write_proc'), self.proc_entries)
136
137 self.log("Starting %d tracers" % len(self.tracers))
138 map(methodcaller('start_tracing'), self.tracers)
139
140 def teardown(self):
141 sleep_time = 5
142 self.log("Sleeping %d seconds to allow buffer flushing" % sleep_time)
143 time.sleep(sleep_time)
144
145 self.log("Stopping tracers")
146 map(methodcaller('stop_tracing'), self.tracers)
147
148 self.log("Switching to Linux scheduler")
149 litmus_util.switch_scheduler("Linux")
150
151 self.log("Saving results in %s" % self.finished_dir)
152 self.__save_results()
153 self.log("Experiment done!")