diff options
Diffstat (limited to 'parse/sched.py')
-rw-r--r-- | parse/sched.py | 85 |
1 files changed, 49 insertions, 36 deletions
diff --git a/parse/sched.py b/parse/sched.py index 5a36da9..6e1fbe6 100644 --- a/parse/sched.py +++ b/parse/sched.py | |||
@@ -41,29 +41,23 @@ class TimeTracker: | |||
41 | # any task is always skipped | 41 | # any task is always skipped |
42 | self.last_record = None | 42 | self.last_record = None |
43 | 43 | ||
44 | self.stored_dur = 0 | ||
45 | |||
46 | def store_time(self, next_record): | 44 | def store_time(self, next_record): |
47 | '''End duration of time.''' | 45 | '''End duration of time.''' |
48 | dur = (self.last_record.when - self.begin) if self.last_record else -1 | 46 | dur = (self.last_record.when - self.begin) if self.last_record else -1 |
49 | dur += self.stored_dur | ||
50 | 47 | ||
51 | if self.next_job == next_record.job: | 48 | if self.next_job == next_record.job: |
52 | self.last_record = next_record | ||
53 | |||
54 | if self.last_record: | 49 | if self.last_record: |
55 | self.matches += 1 | 50 | self.matches += 1 |
56 | 51 | ||
57 | if self.join_job and self.next_job == self.last_record.job: | 52 | self.last_record = next_record |
58 | self.stored_dur += dur | 53 | |
59 | elif dur > 0: | 54 | if dur > 0: |
60 | self.max = max(self.max, dur) | 55 | self.max = max(self.max, dur) |
61 | self.avg *= float(self.num / (self.num + 1)) | 56 | self.avg *= float(self.num / (self.num + 1)) |
62 | self.num += 1 | 57 | self.num += 1 |
63 | self.avg += dur / float(self.num) | 58 | self.avg += dur / float(self.num) |
64 | 59 | ||
65 | self.begin = 0 | 60 | self.begin = 0 |
66 | self.stored_dur = 0 | ||
67 | self.next_job = 0 | 61 | self.next_job = 0 |
68 | else: | 62 | else: |
69 | self.disjoints += 1 | 63 | self.disjoints += 1 |
@@ -81,7 +75,6 @@ class TimeTracker: | |||
81 | class LeveledArray(object): | 75 | class LeveledArray(object): |
82 | """Groups statistics by the level of the task to which they apply""" | 76 | """Groups statistics by the level of the task to which they apply""" |
83 | def __init__(self): | 77 | def __init__(self): |
84 | self.name = name | ||
85 | self.vals = defaultdict(lambda: defaultdict(lambda:[])) | 78 | self.vals = defaultdict(lambda: defaultdict(lambda:[])) |
86 | 79 | ||
87 | def add(self, name, level, value): | 80 | def add(self, name, level, value): |
@@ -92,12 +85,12 @@ class LeveledArray(object): | |||
92 | def write_measurements(self, result): | 85 | def write_measurements(self, result): |
93 | for stat_name, stat_data in self.vals.iteritems(): | 86 | for stat_name, stat_data in self.vals.iteritems(): |
94 | for level, values in stat_data.iteritems(): | 87 | for level, values in stat_data.iteritems(): |
95 | if not values or not sum(values): | 88 | # if not values or not sum(values): |
96 | log_once(SKIP_MSG, SKIP_MSG % stat_name) | 89 | # log_once(SKIP_MSG, SKIP_MSG % stat_name) |
97 | continue | 90 | # continue |
98 | 91 | ||
99 | name = "%s%s" % ("%s-" % level if level else "", stat_name) | 92 | name = "%s%s" % ("%s-" % level.capitalize() if level else "", stat_name) |
100 | result[name] = Measurement(name).from_array(arr) | 93 | result[name] = Measurement(name).from_array(values) |
101 | 94 | ||
102 | # Map of event ids to corresponding class and format | 95 | # Map of event ids to corresponding class and format |
103 | record_map = {} | 96 | record_map = {} |
@@ -201,8 +194,9 @@ class ParamRecord(SchedRecord): | |||
201 | ('class', c_uint8), ('level', c_uint8)] | 194 | ('class', c_uint8), ('level', c_uint8)] |
202 | 195 | ||
203 | def process(self, task_dict): | 196 | def process(self, task_dict): |
197 | level = chr(97 + self.level) | ||
204 | params = TaskParams(self.wcet, self.period, | 198 | params = TaskParams(self.wcet, self.period, |
205 | self.partition, self.level) | 199 | self.partition, level) |
206 | task_dict[self.pid].params = params | 200 | task_dict[self.pid].params = params |
207 | 201 | ||
208 | class ReleaseRecord(SchedRecord): | 202 | class ReleaseRecord(SchedRecord): |
@@ -214,11 +208,13 @@ class ReleaseRecord(SchedRecord): | |||
214 | if data.params: | 208 | if data.params: |
215 | data.misses.start_time(self, self.when + data.params.period) | 209 | data.misses.start_time(self, self.when + data.params.period) |
216 | 210 | ||
211 | NSEC_PER_USEC = 1000 | ||
217 | class CompletionRecord(SchedRecord): | 212 | class CompletionRecord(SchedRecord): |
218 | FIELDS = [('when', c_uint64)] | 213 | FIELDS = [('when', c_uint64), ('load', c_uint64)] |
219 | 214 | ||
220 | def process(self, task_dict): | 215 | def process(self, task_dict): |
221 | task_dict[self.pid].misses.store_time(self) | 216 | task_dict[self.pid].misses.store_time(self) |
217 | task_dict[self.pid].loads += [float(self.load) / NSEC_PER_USEC ] | ||
222 | 218 | ||
223 | class BlockRecord(SchedRecord): | 219 | class BlockRecord(SchedRecord): |
224 | FIELDS = [('when', c_uint64)] | 220 | FIELDS = [('when', c_uint64)] |
@@ -232,9 +228,24 @@ class ResumeRecord(SchedRecord): | |||
232 | def process(self, task_dict): | 228 | def process(self, task_dict): |
233 | task_dict[self.pid].blocks.store_time(self) | 229 | task_dict[self.pid].blocks.store_time(self) |
234 | 230 | ||
231 | class SwitchToRecord(SchedRecord): | ||
232 | FIELDS = [('when', c_uint64)] | ||
233 | |||
234 | def process(self, task_dict): | ||
235 | task_dict[self.pid].execs.start_time(self) | ||
236 | |||
237 | class SwitchAwayRecord(SchedRecord): | ||
238 | FIELDS = [('when', c_uint64)] | ||
239 | |||
240 | def process(self, task_dict): | ||
241 | task_dict[self.pid].execs.store_time(self) | ||
242 | |||
243 | |||
235 | # Map records to sched_trace ids (see include/litmus/sched_trace.h | 244 | # Map records to sched_trace ids (see include/litmus/sched_trace.h |
236 | register_record(2, ParamRecord) | 245 | register_record(2, ParamRecord) |
237 | register_record(3, ReleaseRecord) | 246 | register_record(3, ReleaseRecord) |
247 | register_record(5, SwitchToRecord) | ||
248 | register_record(6, SwitchAwayRecord) | ||
238 | register_record(7, CompletionRecord) | 249 | register_record(7, CompletionRecord) |
239 | register_record(8, BlockRecord) | 250 | register_record(8, BlockRecord) |
240 | register_record(9, ResumeRecord) | 251 | register_record(9, ResumeRecord) |
@@ -250,7 +261,8 @@ def create_task_dict(data_dir, work_dir = None): | |||
250 | output_file = "%s/out-st" % work_dir | 261 | output_file = "%s/out-st" % work_dir |
251 | 262 | ||
252 | task_dict = defaultdict(lambda : | 263 | task_dict = defaultdict(lambda : |
253 | TaskData(None, 1, TimeTracker(), TimeTracker())) | 264 | TaskData(None, 1, [], TimeTracker(), |
265 | TimeTracker(), TimeTracker(True))) | ||
254 | 266 | ||
255 | bin_names = [f for f in os.listdir(data_dir) if re.match(bin_files, f)] | 267 | bin_names = [f for f in os.listdir(data_dir) if re.match(bin_files, f)] |
256 | if not len(bin_names): | 268 | if not len(bin_names): |
@@ -281,11 +293,11 @@ def extract_sched_data(result, data_dir, work_dir): | |||
281 | # Currently unknown where these invalid tasks come from... | 293 | # Currently unknown where these invalid tasks come from... |
282 | continue | 294 | continue |
283 | 295 | ||
284 | level = tdata.config.level | 296 | level = tdata.params.level |
285 | miss = tdata.misses | 297 | miss = tdata.misses |
286 | 298 | ||
287 | record_loss = float(miss.disjoints)/(miss.matches + miss.disjoints) | 299 | record_loss = float(miss.disjoints)/(miss.matches + miss.disjoints) |
288 | stat_data("record-loss", level, record_loss) | 300 | stat_data.add("record-loss", level, record_loss) |
289 | 301 | ||
290 | if record_loss > conf.MAX_RECORD_LOSS: | 302 | if record_loss > conf.MAX_RECORD_LOSS: |
291 | log_once(LOSS_MSG) | 303 | log_once(LOSS_MSG) |
@@ -294,26 +306,27 @@ def extract_sched_data(result, data_dir, work_dir): | |||
294 | miss_ratio = float(miss.num) / miss.matches | 306 | miss_ratio = float(miss.num) / miss.matches |
295 | avg_tard = miss.avg * miss_ratio | 307 | avg_tard = miss.avg * miss_ratio |
296 | 308 | ||
297 | stat_data("miss-ratio", level, miss_ratio) | 309 | stat_data.add("miss-ratio", level, miss_ratio) |
298 | 310 | ||
299 | stat_data("max-tard", level, miss.max / tdata.params.period) | 311 | stat_data.add("max-tard", level, miss.max / tdata.params.period) |
300 | stat_data("avg-tard", level, avg_tard / tdata.params.period) | 312 | stat_data.add("avg-tard", level, avg_tard / tdata.params.period) |
301 | 313 | ||
302 | stat_data("avg-block", level, tdata.blocks.avg / NSEC_PER_MSEC) | 314 | stat_data.add("avg-block", level, tdata.blocks.avg / NSEC_PER_MSEC) |
303 | stat_data("max-block", level, tdata.blocks.max / NSEC_PER_MSEC) | 315 | stat_data.add("max-block", level, tdata.blocks.max / NSEC_PER_MSEC) |
304 | 316 | ||
305 | stat_data.write_measurements(result) | 317 | if tdata.params.level == 'b': |
318 | stat_data.add('LOAD', tdata.params.level, tdata.loads) | ||
306 | 319 | ||
307 | def extract_mc_data(result, data_dir, base_dir): | 320 | stat_data.write_measurements(result) |
308 | task_dict = get_task_data(data_dir) | ||
309 | base_dict = get_task_data(base_dir) | ||
310 | 321 | ||
311 | stat_data = LeveledArray() | 322 | def extract_scaling_data(result, data_dir, base_dir): |
323 | log_once("Scaling factor extraction currently broken, disabled.") | ||
324 | return | ||
312 | 325 | ||
313 | # Only level B loads are measured | 326 | task_dict = create_task_dict(data_dir) |
314 | for tdata in filter(task_dict.iteritems(), lambda x: x.level == 'b'): | 327 | base_dict = create_task_dict(base_dir) |
315 | stat_data.add('load', tdata.config.level, tdata.loads) | ||
316 | 328 | ||
329 | stat_data = LeveledArray() | ||
317 | tasks_by_config = defaultdict(lambda: ScaleData([], [])) | 330 | tasks_by_config = defaultdict(lambda: ScaleData([], [])) |
318 | 331 | ||
319 | # Add task execution times in order of pid to tasks_by_config | 332 | # Add task execution times in order of pid to tasks_by_config |
@@ -324,11 +337,11 @@ def extract_mc_data(result, data_dir, base_dir): | |||
324 | for pid in sorted(tasks.keys()): | 337 | for pid in sorted(tasks.keys()): |
325 | tdata = tasks[pid] | 338 | tdata = tasks[pid] |
326 | 339 | ||
327 | tlist = getattr(tasks_by_config[tdata.params], field) | 340 | tlist = getattr(tasks_by_config[tdata.params], field) |
328 | tlist += [tdata.execs] | 341 | tlist += [tdata.execs] |
329 | 342 | ||
330 | # Write scaling factors | 343 | # Write scaling factors |
331 | for config, scale_data in tasks_by_config: | 344 | for config, scale_data in tasks_by_config.iteritems(): |
332 | if len(scale_data.reg_tasks) != len(scale_data.base_tasks): | 345 | if len(scale_data.reg_tasks) != len(scale_data.base_tasks): |
333 | # Can't make comparison if different numbers of tasks! | 346 | # Can't make comparison if different numbers of tasks! |
334 | continue | 347 | continue |