diff options
Diffstat (limited to 'parse')
| -rw-r--r-- | parse/sched.py | 125 | ||||
| -rw-r--r-- | parse/tuple_table.py | 3 |
2 files changed, 95 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 | ||
diff --git a/parse/tuple_table.py b/parse/tuple_table.py index b56fa6c..6363b80 100644 --- a/parse/tuple_table.py +++ b/parse/tuple_table.py | |||
| @@ -27,6 +27,9 @@ class ColMap(object): | |||
| 27 | 27 | ||
| 28 | return key | 28 | return key |
| 29 | 29 | ||
| 30 | def __contains__(self, col): | ||
| 31 | return col in self.rev_map | ||
| 32 | |||
| 30 | def get_map(self, tuple): | 33 | def get_map(self, tuple): |
| 31 | map = {} | 34 | map = {} |
| 32 | for i in range(0, len(tuple)): | 35 | for i in range(0, len(tuple)): |
