aboutsummaryrefslogtreecommitdiffstats
path: root/parse/sched.py
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2012-10-07 23:40:12 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2012-10-07 23:40:12 -0400
commit5d97a6baf6166b74355c6e744e010949a46fd625 (patch)
tree9a0ac19bd5cb0b5a366fc2e7a9c814a7ab520a18 /parse/sched.py
parentc8cb14963511d5d1a3eb46624bcc0d2bcdf3b9bc (diff)
Split scheduling data by task criticality.
Diffstat (limited to 'parse/sched.py')
-rw-r--r--parse/sched.py125
1 files changed, 76 insertions, 49 deletions
diff --git a/parse/sched.py b/parse/sched.py
index b84e16e..300c569 100644
--- a/parse/sched.py
+++ b/parse/sched.py
@@ -34,7 +34,26 @@ COMPLETION_RECORD = r"(?P<RECORD>" +\
34TaskConfig = namedtuple('TaskConfig', ['cpu','wcet','period','type','level']) 34TaskConfig = namedtuple('TaskConfig', ['cpu','wcet','period','type','level'])
35Task = namedtuple('Task', ['pid', 'config']) 35Task = namedtuple('Task', ['pid', 'config'])
36 36
37class LeveledArray(object):
38 """
39 Groups statistics by the level of the task to which they apply
40 """
41 def __init__(self, name):
42 self.name = name
43 self.vals = defaultdict(lambda:[])
44
45 def add(self, task, value):
46 self.vals[task.config.level] += [value]
47
48 def write_measurements(self, result):
49 for level, arr in self.vals.iteritems():
50 name = "%s%s" % ("%s-" % level if level else "", self.name)
51 result[name] = Measurement(name).from_array(arr)
52
37def get_st_output(data_dir, out_dir): 53def get_st_output(data_dir, out_dir):
54 """
55 Create and return files containing unpacked sched data
56 """
38 bin_files = conf.FILES['sched_data'].format(".*") 57 bin_files = conf.FILES['sched_data'].format(".*")
39 bins = [f for f in os.listdir(data_dir) if re.match(bin_files, f)] 58 bins = [f for f in os.listdir(data_dir) if re.match(bin_files, f)]
40 59
@@ -70,7 +89,7 @@ def get_tasks(data):
70 (e, match.groupdict(), match.group('RECORD'))) 89 (e, match.groupdict(), match.group('RECORD')))
71 return ret 90 return ret
72 91
73def get_tasks_dict(data): 92def get_task_dict(data):
74 tasks_list = get_tasks(data) 93 tasks_list = get_tasks(data)
75 tasks_dict = {} 94 tasks_dict = {}
76 for t in tasks_list: 95 for t in tasks_list:
@@ -89,17 +108,15 @@ def get_task_exits(data):
89 except: 108 except:
90 raise Exception("Invalid exit record, parsed:\n\t%s\n\t%s" % 109 raise Exception("Invalid exit record, parsed:\n\t%s\n\t%s" %
91 (match.groupdict(), m.group('RECORD'))) 110 (match.groupdict(), m.group('RECORD')))
92 111
93 ret += [m] 112 ret += [m]
94 return ret 113 return ret
95
96 114
97def extract_tardy_vals(data, exp_point):
98 ratios = []
99 avg_tards = []
100 max_tards = []
101 115
102 tasks = get_tasks_dict(data) 116def extract_tardy_vals(task_dict, data, exp_point):
117 ratios = LeveledArray("miss-ratio")
118 avg_tards = LeveledArray("avg-rel-tardiness")
119 max_tards = LeveledArray("max-rel-tardiness")
103 120
104 for match in re.finditer(TARDY_RECORD, data): 121 for match in re.finditer(TARDY_RECORD, data):
105 try: 122 try:
@@ -114,35 +131,40 @@ def extract_tardy_vals(data, exp_point):
114 raise Exception("Invalid tardy record:\n\t%s\n\t%s" % 131 raise Exception("Invalid tardy record:\n\t%s\n\t%s" %
115 (match.groupdict(), match.group("RECORD"))) 132 (match.groupdict(), match.group("RECORD")))
116 133
117 if pid not in tasks: 134 if pid not in task_dict:
118 raise Exception("Invalid pid '%d' in tardy record:\n\t%s" % 135 raise Exception("Invalid pid '%d' in tardy record:\n\t%s" %
119 match.group("RECORD")) 136 match.group("RECORD"))
120 137
121 t = tasks[pid] 138 t = task_dict[pid]
122 avg_tards += [ total_tard / (jobs * t.config.period) ] 139 avg_tards.add(t, total_tard / (jobs * t.config.period))
123 max_tards += [ max_tard / t.config.period ] 140 max_tards.add(t, max_tard / t.config.period)
124 ratios += [ misses / jobs ] 141 ratios.add(t, misses / jobs)
125 142
126 exp_point["avg-rel-tard"] = Measurement().from_array(avg_tards) 143 ratios.write_measurements(exp_point)
127 exp_point["max-rel-tard"] = Measurement().from_array(max_tards) 144 avg_tards.write_measurements(exp_point)
128 exp_point["miss-ratio"] = Measurement().from_array(ratios) 145 max_tards.write_measurements(exp_point)
129 146
130def extract_variance(data, exp_point): 147def extract_variance(task_dict, data, exp_point):
131 varz = [] 148 varz = LeveledArray("exec-variance")
132 completions = defaultdict(lambda: []) 149 completions = defaultdict(lambda: [])
150 missed = defaultdict(lambda: int())
133 151
134 for match in re.finditer(COMPLETION_RECORD, data): 152 for match in re.finditer(COMPLETION_RECORD, data):
135 try: 153 try:
136 pid = int(match.group("PID")) 154 pid = int(match.group("PID"))
137 duration = float(match.group("EXEC")) 155 duration = float(match.group("EXEC"))
138 156
139 if not (duration and pid): raise Exception() 157 # Last (exit) record often has exec time of 0
158 missed[pid] += not bool(duration)
159
160 if missed[pid] > 1 or not pid: raise Exception()
140 except: 161 except:
141 raise Exception("Invalid completion record:\n\t%s\n\t%s" % 162 raise Exception("Invalid completion record, missed - %d:"
142 (match.groupdict(), match.group("RECORD"))) 163 "\n\t%s\n\t%s" % (missed[pid], match.groupdict(),
164 match.group("RECORD")))
143 completions[pid] += [duration] 165 completions[pid] += [duration]
144 166
145 for (pid, durations) in completions: 167 for pid, durations in completions.iteritems():
146 job_times = np.array(durations) 168 job_times = np.array(durations)
147 169
148 # Coefficient of variation 170 # Coefficient of variation
@@ -150,32 +172,22 @@ def extract_variance(data, exp_point):
150 # Correction, assuming normal distributions 172 # Correction, assuming normal distributions
151 corrected = (1 + 1/(4 * len(job_times))) * cv 173 corrected = (1 + 1/(4 * len(job_times))) * cv
152 174
153 varz.append(corrected) 175 varz.add(task_dict[pid], corrected)
154
155 exp_point['exec-var'] = Measurement().from_array(varz)
156
157def extract_sched_data(data_file, result):
158 with open(data_file, 'r') as f:
159 data = f.read()
160 176
161 extract_tardy_vals(data, result) 177 varz.write_measurements(exp_point)
162 extract_variance(data, result)
163 178
164def config_exit_stats(file): 179def config_exit_stats(task_dict, file):
165 with open(file, 'r') as f: 180 with open(file, 'r') as f:
166 data = f.read() 181 data = f.read()
167
168 tasks = get_tasks(data)
169 182
170 # Dictionary of task exit measurements by pid 183 # Dictionary of task exit measurements by pid
171 exits = get_task_exits(data) 184 exits = get_task_exits(data)
172
173 exit_dict = dict((e.id, e) for e in exits) 185 exit_dict = dict((e.id, e) for e in exits)
174 186
175 # Dictionary where keys are configurations, values are list 187 # Dictionary where keys are configurations, values are list
176 # of tasks with those configuratino 188 # of tasks with those configuratino
177 config_dict = defaultdict(lambda: []) 189 config_dict = defaultdict(lambda: [])
178 for t in tasks: 190 for t in task_dict.itervalues():
179 config_dict[t.config] += [t] 191 config_dict[t.config] += [t]
180 192
181 for config in config_dict: 193 for config in config_dict:
@@ -185,7 +197,6 @@ def config_exit_stats(file):
185 if not t.pid in exit_dict: 197 if not t.pid in exit_dict:
186 raise Exception("Missing exit record for task '%s' in '%s'" % 198 raise Exception("Missing exit record for task '%s' in '%s'" %
187 (t, file)) 199 (t, file))
188
189 exit_list = [exit_dict[t.pid] for t in task_list] 200 exit_list = [exit_dict[t.pid] for t in task_list]
190 config_dict[config] = exit_list 201 config_dict[config] = exit_list
191 202
@@ -195,20 +206,22 @@ saved_stats = {}
195def get_base_stats(base_file): 206def get_base_stats(base_file):
196 if base_file in saved_stats: 207 if base_file in saved_stats:
197 return saved_stats[base_file] 208 return saved_stats[base_file]
198 result = config_exit_stats(base_file) 209 with open(base_file, 'r') as f:
210 data = f.read()
211 result = config_exit_stats(data)
199 saved_stats[base_file] = result 212 saved_stats[base_file] = result
200 return result 213 return result
201 214
202def extract_scaling_data(data_file, base_file, result): 215def extract_scaling_data(task_dict, data, result, base_file):
203 # Generate trees of tasks with matching configurations 216 # Generate trees of tasks with matching configurations
204 data_stats = config_exit_stats(data_file) 217 data_stats = config_exit_stats(data)
205 base_stats = get_base_stats(base_file) 218 base_stats = get_base_stats(base_file)
206 219
207 # Scaling factors are calculated by matching groups of tasks with the same 220 # Scaling factors are calculated by matching groups of tasks with the same
208 # config, then comparing task-to-task exec times in order of PID within 221 # config, then comparing task-to-task exec times in order of PID within
209 # each group 222 # each group
210 max_scales = [] 223 max_scales = LeveledArray("max-scaling")
211 avg_scales = [] 224 avg_scales = LeveledArray("avg-scaling")
212 225
213 for config in data_stats: 226 for config in data_stats:
214 if len(data_stats[config]) != len(base_stats[config]): 227 if len(data_stats[config]) != len(base_stats[config]):
@@ -220,8 +233,22 @@ def extract_scaling_data(data_file, base_file, result):
220 avg_scale = float(base_stat[Type.Avg]) / float(base_stat[Type.Avg]) 233 avg_scale = float(base_stat[Type.Avg]) / float(base_stat[Type.Avg])
221 max_scale = float(base_stat[Type.Max]) / float(base_stat[Type.Max]) 234 max_scale = float(base_stat[Type.Max]) / float(base_stat[Type.Max])
222 235
223 avg_scales += [avg_scale] 236 task = task_dict[data_stat.id]
224 max_scales += [max_scale] 237
238 avg_scales.add(task, avg_scale)
239 max_scales.add(task, max_scale)
240
241 avg_scales.write_measurements(result)
242 max_scales.write_measurements(result)
243
244def extract_sched_data(data_file, result, base_file):
245 with open(data_file, 'r') as f:
246 data = f.read()
247
248 task_dict = get_task_dict(data)
249
250 extract_tardy_vals(task_dict, data, result)
251 extract_variance(task_dict, data, result)
225 252
226 result['max-scale'] = Measurement().from_array(max_scales) 253 if (base_file):
227 result['avg-scale'] = Measurement().from_array(avg_scales) 254 extract_scaling_data(task_dict, data, result, base_file)