30005cc8b56507585ddc8edcbfaa91f69a5ebf07
[lttng-ci.git] / scripts / lttng-baremetal-tests / generate-plots.py
1 # Copyright (C) 2017 - Francis Deslauriers <francis.deslauriers@efficios.com>
2 #
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation, either version 3 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16
17 import os, sys
18 import numpy as np
19 import pandas as pd
20
21 #Set Matplotlib to use the PNG non interactive backend
22 import matplotlib as mpl
23 mpl.use('Agg')
24
25 import matplotlib.pyplot as plt
26 from matplotlib.ticker import MaxNLocator
27 from cycler import cycler
28 from collections import OrderedDict
29
30 def rename_cols(df):
31 new_cols = {'baseline_1thr_peritermean': 'basel_1thr',
32 'baseline_2thr_peritermean': 'basel_2thr',
33 'baseline_4thr_peritermean': 'basel_4thr',
34 'baseline_8thr_peritermean': 'basel_8thr',
35 'baseline_16thr_peritermean': 'basel_16thr',
36 'lttng_1thr_peritermean': 'lttng_1thr',
37 'lttng_2thr_peritermean': 'lttng_2thr',
38 'lttng_4thr_peritermean': 'lttng_4thr',
39 'lttng_8thr_peritermean': 'lttng_8thr',
40 'lttng_16thr_peritermean': 'lttng_16thr',
41 'baseline_1thr_periterstdev': 'basel_1thr_stdev',
42 'baseline_2thr_periterstdev': 'basel_2thr_stdev',
43 'baseline_4thr_periterstdev': 'basel_4thr_stdev',
44 'baseline_8thr_periterstdev': 'basel_8thr_stdev',
45 'baseline_16thr_periterstdev': 'basel_16thr_stdev',
46 'lttng_1thr_periterstdev': 'lttng_1thr_stdev',
47 'lttng_2thr_periterstdev': 'lttng_2thr_stdev',
48 'lttng_4thr_periterstdev': 'lttng_4thr_stdev',
49 'lttng_8thr_periterstdev': 'lttng_8thr_stdev',
50 'lttng_16thr_periterstdev': 'lttng_16thr_stdev'
51 }
52 df.rename(columns=new_cols, inplace=True)
53 return df
54
55 def convert_us_to_ns(df):
56 cols = [col for col in df.columns if 'periter' in col]
57 df[cols] = df[cols].apply(lambda x: x*1000)
58 return df
59
60 def create_plot(df, graph_type):
61 # We map all test configurations and their
62 # respective color
63 conf_to_color = OrderedDict([
64 ('basel_1thr','lightcoral'),
65 ('lttng_1thr','red'),
66 ('basel_2thr','gray'),
67 ('lttng_2thr','black'),
68 ('basel_4thr','chartreuse'),
69 ('lttng_4thr','forestgreen'),
70 ('basel_8thr','deepskyblue'),
71 ('lttng_8thr','mediumblue'),
72 ('basel_16thr','orange'),
73 ('lttng_16thr','saddlebrown')])
74
75 # We create a list for each of the subplots
76 baseline = [x for x in conf_to_color.keys() if 'basel' in x]
77 lttng = [x for x in conf_to_color.keys() if 'lttng' in x]
78 one_thr = [x for x in conf_to_color.keys() if '_1thr' in x]
79 two_thr = [x for x in conf_to_color.keys() if '_2thr' in x]
80 four_thr = [x for x in conf_to_color.keys() if '_4thr' in x]
81 eight_thr = [x for x in conf_to_color.keys() if '_8thr' in x]
82 sixteen_thr = [x for x in conf_to_color.keys() if '_16thr' in x]
83
84 plots = [baseline, lttng, one_thr, two_thr, four_thr, eight_thr, sixteen_thr]
85
86 title='Meantime per syscalls for {} testcase'.format(graph_type)
87
88 # Create a axe object for each sub-plots
89 f, arrax = plt.subplots(len(plots), sharex=True, figsize=(16, 25))
90 f.suptitle(title, fontsize=20)
91
92 for (ax, data_cols) in zip(arrax, plots):
93 curr_df = df[data_cols]
94
95 stdev_cols = ['{}_stdev'.format(x) for x in data_cols]
96 # Extract the color for each configuration
97 colors = [conf_to_color[x] for x in data_cols]
98
99 # set the color cycler for this plot
100 ax.set_prop_cycle(cycler('color', colors))
101
102 # Plot each line and its errorbars
103 for (data, stdev) in zip(data_cols, stdev_cols):
104 ax.errorbar(x=df.index.values, y=df[data], yerr=df[stdev], marker='o')
105
106 ax.set_ylim(0)
107 ax.grid()
108 ax.set_xlabel('Jenkins Build ID')
109 ax.set_ylabel('Meantime per syscall [us]')
110
111 ax.xaxis.set_major_locator(MaxNLocator(integer=True))
112
113 ax.legend(prop={'family': 'monospace'},
114 labels=curr_df.columns.values, bbox_to_anchor=(1.2,1))
115
116 plt.subplots_adjust(top=0.95)
117 plt.savefig('{}.png'.format(graph_type), bbox_inches='tight')
118
119 # Writes a file that contains commit id of all configurations shown in the
120 # plots
121 def create_metadata_file(res_dir):
122 list_ = []
123 for dirname, dirnames, res_files in os.walk('./'+res_dir):
124 if len(dirnames) > 0:
125 continue
126 metadata = pd.read_csv(os.path.join(dirname, 'metadata.csv'))
127 list_.append(metadata)
128
129 df = pd.concat(list_)
130 df.index=df.build_id
131 df.sort_index(inplace=True)
132 df.to_csv('metadata.csv', index=False)
133
134 #Iterates over a result directory and creates the plots for the different
135 #testcases
136 def create_plots(res_dir):
137 df = pd.DataFrame()
138 metadata_df = pd.DataFrame()
139 list_ = []
140 for dirname, dirnames, res_files in os.walk('./'+res_dir):
141 if len(dirnames) > 0:
142 continue
143 metadata = pd.read_csv(os.path.join(dirname, 'metadata.csv'))
144
145 for res in res_files:
146 if res in 'metadata.csv':
147 continue
148 tmp = pd.read_csv(os.path.join(dirname, res))
149 #Use the build id as the index for the dataframe for filtering
150 tmp.index = metadata.build_id
151 #Add the testcase name to the row for later filtering
152 tmp['testcase'] = res.split('.')[0]
153 list_.append(tmp)
154
155 df = pd.concat(list_)
156 df = convert_us_to_ns(df)
157 df = rename_cols(df)
158 df.sort_index(inplace=True)
159
160 #Go over the entire dataframe by testcase and create a plot for each type
161 for testcase in df.testcase.unique():
162 df_testcase = df.loc[df['testcase'] == testcase]
163 create_plot(df=df_testcase, graph_type=testcase)
164
165 def main():
166 res_path = sys.argv[1]
167 create_plots(os.path.join(res_path))
168 create_metadata_file(os.path.join(res_path))
169
170 if __name__ == '__main__':
171 main()
This page took 0.033825 seconds and 4 git commands to generate.