diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-09-30 18:25:38 -0400 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-09-30 18:25:38 -0400 |
commit | c8cb14963511d5d1a3eb46624bcc0d2bcdf3b9bc (patch) | |
tree | 4b44c2814c085b384563bc27b50fdbe8caebe590 /parse/sched.py | |
parent | c6adbabd0bf897a1e750fe07bf068e285dd82108 (diff) |
Added more robust error handling inspired by color tests.
Diffstat (limited to 'parse/sched.py')
-rw-r--r-- | parse/sched.py | 125 |
1 files changed, 92 insertions, 33 deletions
diff --git a/parse/sched.py b/parse/sched.py index 5e3ba6b..b84e16e 100644 --- a/parse/sched.py +++ b/parse/sched.py | |||
@@ -1,6 +1,5 @@ | |||
1 | """ | 1 | """ |
2 | TODO: make regexes indexable by name | 2 | TODO: No longer very pythonic, lot of duplicate code |
3 | |||
4 | """ | 3 | """ |
5 | 4 | ||
6 | import config.config as conf | 5 | import config.config as conf |
@@ -12,7 +11,27 @@ import subprocess | |||
12 | from collections import namedtuple,defaultdict | 11 | from collections import namedtuple,defaultdict |
13 | from point import Measurement,Type | 12 | from point import Measurement,Type |
14 | 13 | ||
15 | TaskConfig = namedtuple('TaskConfig', ['cpu','wcet','period']) | 14 | PARAM_RECORD = r"(?P<RECORD>" +\ |
15 | r"PARAM *?(?P<PID>\d+)\/.*?" +\ | ||
16 | r"cost:\s+(?P<WCET>[\d\.]+)ms.*?" +\ | ||
17 | r"period.*?(?P<PERIOD>[\d.]+)ms.*?" +\ | ||
18 | r"part.*?(?P<CPU>\d+)[, ]*" +\ | ||
19 | r"(?:class=(?P<CLASS>\w+))?[, ]*" +\ | ||
20 | r"(?:level=(?P<LEVEL>\w+))?).*$" | ||
21 | EXIT_RECORD = r"(?P<RECORD>" +\ | ||
22 | r"TASK_EXIT *?(?P<PID>\d+)/.*?" +\ | ||
23 | r"Avg.*?(?P<AVG>\d+).*?" +\ | ||
24 | r"Max.*?(?P<MAX>\d+))" | ||
25 | TARDY_RECORD = r"(?P<RECORD>" +\ | ||
26 | r"TARDY.*?(?P<PID>\d+)/(?P<JOB>\d+).*?" +\ | ||
27 | r"Tot.*?(?P<TOTAL>[\d\.]+).*?ms.*?" +\ | ||
28 | r"(?P<MAX>[\d\.]+).*?ms.*?" +\ | ||
29 | r"(?P<MISSES>[\d\.]+))" | ||
30 | COMPLETION_RECORD = r"(?P<RECORD>" +\ | ||
31 | r"COMPLETION.*?(?P<PID>\d+)/.*?" +\ | ||
32 | r"(?P<EXEC>[\d\.]+)ms)" | ||
33 | |||
34 | TaskConfig = namedtuple('TaskConfig', ['cpu','wcet','period','type','level']) | ||
16 | Task = namedtuple('Task', ['pid', 'config']) | 35 | Task = namedtuple('Task', ['pid', 'config']) |
17 | 36 | ||
18 | def get_st_output(data_dir, out_dir): | 37 | def get_st_output(data_dir, out_dir): |
@@ -34,18 +53,43 @@ def get_st_output(data_dir, out_dir): | |||
34 | return output_file | 53 | return output_file |
35 | 54 | ||
36 | def get_tasks(data): | 55 | def get_tasks(data): |
37 | reg = r"PARAM *?(\d+)\/.*?cost:\s+([\d\.]+)ms.*?period.*?([\d.]+)ms.*?part.*?(\d+)" | ||
38 | ret = [] | 56 | ret = [] |
39 | for match in re.findall(reg, data): | 57 | for match in re.finditer(PARAM_RECORD, data, re.M): |
40 | t = Task(match[0], TaskConfig(match[3],match[1],match[2])) | 58 | try: |
41 | ret += [t] | 59 | t = Task( int(match.group('PID')), |
60 | TaskConfig( int(match.group('CPU')), | ||
61 | float(match.group('WCET')), | ||
62 | float(match.group('PERIOD')), | ||
63 | match.group("CLASS"), | ||
64 | match.group("LEVEL"))) | ||
65 | if not (t.config.period and t.pid): | ||
66 | raise Exception() | ||
67 | ret += [t] | ||
68 | except Exception as e: | ||
69 | raise Exception("Invalid task record: %s\nparsed:\n\t%s\n\t%s" % | ||
70 | (e, match.groupdict(), match.group('RECORD'))) | ||
42 | return ret | 71 | return ret |
43 | 72 | ||
73 | def get_tasks_dict(data): | ||
74 | tasks_list = get_tasks(data) | ||
75 | tasks_dict = {} | ||
76 | for t in tasks_list: | ||
77 | tasks_dict[t.pid] = t | ||
78 | return tasks_dict | ||
79 | |||
44 | def get_task_exits(data): | 80 | def get_task_exits(data): |
45 | reg = r"TASK_EXIT *?(\d+)/.*?Avg.*?(\d+).*?Max.*?(\d+)" | ||
46 | ret = [] | 81 | ret = [] |
47 | for match in re.findall(reg, data): | 82 | for match in re.finditer(EXIT_RECORD, data): |
48 | m = Measurement(match[0], {Type.Max : match[2], Type.Avg : match[1]}) | 83 | try: |
84 | m = Measurement( int(match.group('PID')), | ||
85 | {Type.Max : float(match.group('MAX')), | ||
86 | Type.Avg : float(match.group('AVG'))}) | ||
87 | for (type, value) in m: | ||
88 | if not value: raise Exception() | ||
89 | except: | ||
90 | raise Exception("Invalid exit record, parsed:\n\t%s\n\t%s" % | ||
91 | (match.groupdict(), m.group('RECORD'))) | ||
92 | |||
49 | ret += [m] | 93 | ret += [m] |
50 | return ret | 94 | return ret |
51 | 95 | ||
@@ -55,40 +99,51 @@ def extract_tardy_vals(data, exp_point): | |||
55 | avg_tards = [] | 99 | avg_tards = [] |
56 | max_tards = [] | 100 | max_tards = [] |
57 | 101 | ||
58 | for t in get_tasks(data): | 102 | tasks = get_tasks_dict(data) |
59 | reg = r"TARDY.*?" + t.pid + "/(\d+).*?Tot.*?([\d\.]+).*?ms.*?([\d\.]+).*?ms.*?([\d\.]+)" | ||
60 | matches = re.findall(reg, data) | ||
61 | if len(matches) != 0: | ||
62 | jobs = float(matches[0][0]) | ||
63 | 103 | ||
64 | total_tard = float(matches[0][1]) | 104 | for match in re.finditer(TARDY_RECORD, data): |
65 | avg_tard = (total_tard / jobs) / float(t.config.period) | 105 | try: |
66 | max_tard = float(matches[0][2]) / float(t.config.period) | 106 | pid = int(match.group("PID")) |
107 | jobs = int(match.group("JOB")) | ||
108 | misses = int(match.group("MISSES")) | ||
109 | total_tard = float(match.group("TOTAL")) | ||
110 | max_tard = float(match.group("MAX")) | ||
67 | 111 | ||
68 | misses = float(matches[0][3]) | 112 | if not (jobs and pid): raise Exception() |
69 | if misses != 0: | 113 | except: |
70 | miss_ratio = (misses / jobs) | 114 | raise Exception("Invalid tardy record:\n\t%s\n\t%s" % |
71 | else: | 115 | (match.groupdict(), match.group("RECORD"))) |
72 | miss_ratio = 0 | ||
73 | 116 | ||
74 | ratios += [miss_ratio] | 117 | if pid not in tasks: |
75 | avg_tards += [avg_tard] | 118 | raise Exception("Invalid pid '%d' in tardy record:\n\t%s" % |
76 | max_tards += [max_tard] | 119 | match.group("RECORD")) |
120 | |||
121 | t = tasks[pid] | ||
122 | avg_tards += [ total_tard / (jobs * t.config.period) ] | ||
123 | max_tards += [ max_tard / t.config.period ] | ||
124 | ratios += [ misses / jobs ] | ||
77 | 125 | ||
78 | exp_point["avg-rel-tard"] = Measurement().from_array(avg_tards) | 126 | exp_point["avg-rel-tard"] = Measurement().from_array(avg_tards) |
79 | exp_point["max-rel-tard"] = Measurement().from_array(max_tards) | 127 | exp_point["max-rel-tard"] = Measurement().from_array(max_tards) |
80 | exp_point["miss-ratio"] = Measurement().from_array(ratios) | 128 | exp_point["miss-ratio"] = Measurement().from_array(ratios) |
81 | 129 | ||
82 | def extract_variance(data, exp_point): | 130 | def extract_variance(data, exp_point): |
83 | varz = [] | 131 | varz = [] |
84 | for t in get_tasks(data): | 132 | completions = defaultdict(lambda: []) |
85 | reg = r"COMPLETION.*?" + t.pid + r".*?([\d\.]+)ms" | 133 | |
86 | matches = re.findall(reg, data) | 134 | for match in re.finditer(COMPLETION_RECORD, data): |
135 | try: | ||
136 | pid = int(match.group("PID")) | ||
137 | duration = float(match.group("EXEC")) | ||
87 | 138 | ||
88 | if len(matches) == 0: | 139 | if not (duration and pid): raise Exception() |
89 | return 0 | 140 | except: |
141 | raise Exception("Invalid completion record:\n\t%s\n\t%s" % | ||
142 | (match.groupdict(), match.group("RECORD"))) | ||
143 | completions[pid] += [duration] | ||
90 | 144 | ||
91 | job_times = np.array(filter(lambda x: float(x) != 0, matches), dtype=np.float) | 145 | for (pid, durations) in completions: |
146 | job_times = np.array(durations) | ||
92 | 147 | ||
93 | # Coefficient of variation | 148 | # Coefficient of variation |
94 | cv = job_times.std() / job_times.mean() | 149 | cv = job_times.std() / job_times.mean() |
@@ -127,6 +182,10 @@ def config_exit_stats(file): | |||
127 | task_list = sorted(config_dict[config]) | 182 | task_list = sorted(config_dict[config]) |
128 | 183 | ||
129 | # Replace tasks with corresponding exit stats | 184 | # Replace tasks with corresponding exit stats |
185 | if not t.pid in exit_dict: | ||
186 | raise Exception("Missing exit record for task '%s' in '%s'" % | ||
187 | (t, file)) | ||
188 | |||
130 | exit_list = [exit_dict[t.pid] for t in task_list] | 189 | exit_list = [exit_dict[t.pid] for t in task_list] |
131 | config_dict[config] = exit_list | 190 | config_dict[config] = exit_list |
132 | 191 | ||