7 import numpy.linalg as nplag
8 import matplotlib.pyplot as plt
13 import psycopg2.extras
19 #matplotlib.rcParams['font.size'] = 8
20 matplotlib.rcParams['savefig.bbox'] = 'tight'
22 conn = psycopg2.connect(dbname="linux-conf-perf", connection_factory=psycopg2.extras.NamedTupleConnection)
25 # cur.execute("SELECT m.value, t.git_describe FROM measure AS m JOIN toolsgit AS t ON m.toolgit = t.id;")
26 # for row in cur.fetchall():
29 def fill_in_missing_values():
32 cur.execute("SELECT output, id, conf, measurement, result, value, linuxgit, toolgit FROM measure WHERE value IS NULL AND result <> 'failed';")
33 result_re = re.compile("! T: 0 \(.*\) P:.* I:.* C:.* Min: *(?P<min>\d+) Act: *(?P<act>\d+) Avg: *(?P<avg>\d+) Max: *(?P<max>\d+) ok")
34 for row in cur.fetchall():
35 for line in row.output.split('\n'):
36 match = result_re.match(line)
38 value = int(match.group('max'))
39 cur2.execute("UPDATE measure SET value = %(val)s WHERE id = %(id)s", {'val': value, 'id': row.id })
44 cur.execute("SELECT output FROM measure WHERE result='failed' and toolgit=11;")
45 for row in cur.fetchall():
46 with subprocess.Popen(['less', '+G'], stdin=subprocess.PIPE) as proc:
47 proc.communicate(input=row.output.encode('utf-8'))
50 """Linux configuration fetched from DB, key is option name, value is
53 def __init__(self, id):
54 cur.execute("SELECT config FROM configurations WHERE id=%s;", (id,))
56 for opt in conf.config.split('\n'):
57 (key, val) = opt.split('=')
60 class VariableOptions(dict):
61 """Dictionary of config options that change value during experiments.
62 Key is the config name, value is the index to the matrix A
65 def __init__(self, measurements):
68 for m in measurements:
70 config = Config(m.conf)
71 for (key, val) in config.items():
72 if key not in all_options:
73 all_options[key] = val
75 if all_options[key] != val and key not in self:
79 def update_order(self):
81 for key in sorted(self.keys()):
82 self[key] = len(self.order)
83 self.order.append(key)
86 return self.order.__iter__()
88 def name_by_index(self, index):
89 return self.order[index]
93 print("%-40s %s" % (k, self[k]))
95 def load_configs(measurements, options):
97 configs = pickle.load(open('configs.pickle', 'rb'))
100 for i in range(len(measurements)):
101 config = Config(measurements[i].conf)
102 keys = config.copy().keys()
106 configs[measurements[i].conf] = config
107 pickle.dump(configs, open('configs.pickle', 'wb'))
110 def construct_ab(options, measurements, configs):
111 A = np.mat(np.zeros((len(measurements), len(options) + 1)))
112 B = np.mat(np.zeros((len(measurements), 1)))
114 for i in range(len(measurements)):
115 config = configs[measurements[i].conf]
116 A[i, len(options)] = 1
117 B[i] = measurements[i].value
118 for j in range(len(options)):
119 A[i,j] = 1 if config[options.name_by_index(j)] == 'y' else 0
122 def plot_values(measurements, configs, measurements_est, highlight_options):
123 print(measurements_est.__class__, measurements_est.shape)
124 B = np.mat(np.zeros((len(measurements),1)))
125 for i in range(len(measurements)):
126 B[i] = measurements[i].value
128 idx = np.argsort(B, 0)
130 measurements = sorted(measurements, key=lambda x: x.value)
131 measurements_est = measurements_est[idx, 0]
133 plt.plot(measurements_est, 'x', color='#aaaaaa')
135 plt.gcf().set_size_inches(8,4)
136 plt.plot(B, color='b')
137 plt.xlabel('Configuration')
138 plt.ylabel('cyclictest result [µs]')
140 for o in highlight_options if 0 else []:
144 for i in range(len(measurements)):
145 if configs[measurements[i].conf][o] == 'y':
147 y.append(measurements[i].value)
148 plt.plot(x, (yy*5-150)*np.ones(len(x)), '+')
150 plt.legend(['Model', 'Measured'] + [o[7:] for o in highlight_options], loc = 'upper left')
152 plt.xlim(0,len(measurements))
153 plt.savefig('measurements.pdf')
156 def save_options(options):
157 json.dump(options, open('options.json', 'w'), indent=' ', sort_keys=True)
159 def load_variable_options(measurements):
160 if os.path.exists('options.json'):
161 options = VariableOptions([])
162 options.update(json.load(open('options.json', 'r')))
163 options.update_order()
165 options = VariableOptions(measurements)
166 save_options(options)
170 def remove_linerly_dependent_options(options, measurements, configs):
171 (A,B) = construct_ab(options, measurements, configs)
172 rank = nplag.matrix_rank(A)
174 if rank == A.shape[1]:
178 for k in sorted(o.keys()):
180 options.update_order()
181 (A,B) = construct_ab(options, measurements, configs)
182 if nplag.matrix_rank(A) != rank:
184 options.update_order()
190 def __init__(self, option_name, regression=None, yes_count=None):
191 self.option_name = option_name
192 self.regression = regression
193 self.yes_count = int(yes_count)
194 self.measure_diff = []
196 def calc_measure_diff(self, A, B, options):
197 oidx = options[self.option_name]
198 for m1 in range(A.shape[0]):
202 for m2 in range(A.shape[0]):
203 if A[m2,oidx] == 0 and (row == A[m2]).all():
204 self.measure_diff.append(B[m1] - B[m2])
207 def plot_bars(results):
208 y_pos = np.arange(len(results), 0, -1)
209 regr = np.array([r.regression for r in results])
210 diff = np.array([np.array(r.measure_diff).mean() for r in results])
212 fig, ax = plt.subplots()
213 fig.set_size_inches(8,12)
216 ax.set_yticklabels([r.option_name[7:] for r in results], fontsize=12)
217 rects1 = ax.barh(y_pos, regr, height=0.35, color='b')
218 rects2 = ax.barh(y_pos+0.35, diff, height=0.35, color='w', hatch='//')
219 ax.legend(['regression', 'two measurement diff'])
221 ax.set_xlabel("Config option influence [µs]")
222 plt.savefig('option_res.pdf')
226 cur.execute("SELECT conf, value FROM measure WHERE result='nominal' AND toolgit IN (1, 11);")
227 measurements = cur.fetchall()
229 options = load_variable_options(measurements)
230 configs = load_configs(measurements, options)
232 options = remove_linerly_dependent_options(options, measurements, configs)
233 save_options(options)
235 (A,B) = construct_ab(options, measurements, configs)
237 #np.set_printoptions(threshold = float('nan'), linewidth = 300)
238 np.set_printoptions(edgeitems = 9, linewidth = 80)
241 result = nplag.lstsq(A, B)
245 results = pickle.load(open('results.pickle', 'rb'))
251 r = OptionResult(k, regression=x.item(idx), yes_count=A[:,idx].sum())
252 r.calc_measure_diff(A, B, options)
255 results.sort(key=lambda r: r.regression)
256 pickle.dump(results, open('results.pickle', 'wb'))
259 print("{option_name:<40} {regression:7.2f} {yes_count:4d} {percent:2}%".format(percent=10, **r.__dict__))
260 print("%-40s %6.2f" % ("common", x[len(options)]))
263 plot_values(measurements, configs, A*x, [r.option_name for r in results])
266 if __name__ == '__main__':