jjb: lltng-modules: fix ceiling for stable-2.10 vanilla jobs
[lttng-ci.git] / scripts / system-tests / generate-plots.py
CommitLineData
b87dc589
FD
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
17import os, sys
18import numpy as np
19import pandas as pd
20
21#Set Matplotlib to use the PNG non interactive backend
22import matplotlib as mpl
23mpl.use('Agg')
24
25import matplotlib.pyplot as plt
26from matplotlib.ticker import MaxNLocator
27from cycler import cycler
58a2fcd3 28from collections import OrderedDict
b87dc589
FD
29
30def rename_cols(df):
f758d98b
FD
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',
094ca2d3
FD
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'
b87dc589
FD
51 }
52 df.rename(columns=new_cols, inplace=True)
53 return df
54
c5545ca0
FD
55def 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
b87dc589 60def create_plot(df, graph_type):
58a2fcd3
FD
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]
b87dc589 85
42413939 86 title='Meantime per event for {} testcase'.format(graph_type)
b87dc589 87
58a2fcd3
FD
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)
b87dc589 91
58a2fcd3 92 for (ax, data_cols) in zip(arrax, plots):
094ca2d3
FD
93 curr_df = df[data_cols]
94
58a2fcd3
FD
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
094ca2d3 99 # set the color cycler for this plot
b87dc589 100 ax.set_prop_cycle(cycler('color', colors))
094ca2d3
FD
101
102 # Plot each line and its errorbars
103 for (data, stdev) in zip(data_cols, stdev_cols):
bb43133f 104 ax.errorbar(x=df.index.values, y=df[data].values, yerr=df[stdev].values, marker='o')
094ca2d3 105
b87dc589
FD
106 ax.set_ylim(0)
107 ax.grid()
108 ax.set_xlabel('Jenkins Build ID')
42413939 109 ax.set_ylabel('Meantime per event [us]')
58a2fcd3 110
bb43133f 111 ax.xaxis.set_major_locator(MaxNLocator(integer=True, nbins=30))
b87dc589 112
58a2fcd3
FD
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)
b87dc589
FD
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
121def 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
f18335da
FD
126 try:
127 metadata = pd.read_csv(os.path.join(dirname, 'metadata.csv'))
128 except Exception:
129 print('Omitting run {} because metadata.csv is missing'.format(dirname))
130 continue
b87dc589
FD
131 list_.append(metadata)
132
e7e59cc4 133 df = pd.concat(list_, sort=True)
b87dc589
FD
134 df.index=df.build_id
135 df.sort_index(inplace=True)
136 df.to_csv('metadata.csv', index=False)
137
138#Iterates over a result directory and creates the plots for the different
139#testcases
140def create_plots(res_dir):
141 df = pd.DataFrame()
142 metadata_df = pd.DataFrame()
143 list_ = []
144 for dirname, dirnames, res_files in os.walk('./'+res_dir):
145 if len(dirnames) > 0:
146 continue
f18335da
FD
147 try:
148 metadata = pd.read_csv(os.path.join(dirname, 'metadata.csv'))
149 except Exception:
150 print('Omitting run {} because metadata.csv is missing'.format(dirname))
151 continue
b87dc589
FD
152
153 for res in res_files:
154 if res in 'metadata.csv':
155 continue
156 tmp = pd.read_csv(os.path.join(dirname, res))
157 #Use the build id as the index for the dataframe for filtering
158 tmp.index = metadata.build_id
159 #Add the testcase name to the row for later filtering
160 tmp['testcase'] = res.split('.')[0]
161 list_.append(tmp)
162
e7e59cc4 163 df = pd.concat(list_, sort=True)
c5545ca0 164 df = convert_us_to_ns(df)
b87dc589
FD
165 df = rename_cols(df)
166 df.sort_index(inplace=True)
167
168 #Go over the entire dataframe by testcase and create a plot for each type
169 for testcase in df.testcase.unique():
170 df_testcase = df.loc[df['testcase'] == testcase]
171 create_plot(df=df_testcase, graph_type=testcase)
172
173def main():
174 res_path = sys.argv[1]
175 create_plots(os.path.join(res_path))
176 create_metadata_file(os.path.join(res_path))
177
178if __name__ == '__main__':
179 main()
This page took 0.032682 seconds and 4 git commands to generate.