1/*
2 * performance_util.hpp
3 *
4 * Created on: Jul 21, 2019
5 * Author: i-bird
6 */
7
8#ifndef PERFORMANCE_UTIL_HPP_
9#define PERFORMANCE_UTIL_HPP_
10
11#include <boost/lexical_cast.hpp>
12#include <boost/filesystem.hpp>
13#include <boost/property_tree/ptree.hpp>
14#include <boost/property_tree/xml_parser.hpp>
15
16static void addUpdtateTime(GoogleChart & cg, int np)
17{
18 time_t t = time(0); // get time now
19 struct tm * now = localtime( & t );
20
21 std::stringstream str;
22
23 std::string commit;
24 commit = exec("git rev-parse HEAD");
25
26 str << "<h3>Updated: " << now->tm_mday << "/" << now->tm_mon + 1 << "/" << now->tm_year+1900 << " " << now->tm_hour << ":" << now->tm_min << ":"
27 << now->tm_sec << " commit: " << commit << " run with: " << np << " processes" << std::endl;
28
29 cg.addHTML(str.str());
30}
31
32static inline void warning_set(int & warning_level, double mean, double mean_ref, double sigma)
33{
34 int warning_level_candidate;
35
36 if (mean - mean_ref < -2.0*sigma )
37 warning_level_candidate = -1;
38 else if (mean - mean_ref < 2.0*sigma)
39 warning_level_candidate = 0;
40 else if (mean - mean_ref < 3.0*sigma)
41 warning_level_candidate = 1;
42 else
43 warning_level_candidate = 2;
44
45 if (warning_level_candidate > warning_level)
46 warning_level = warning_level_candidate;
47}
48
49static inline void addchartarea(std::string & chart_area, int lvl)
50{
51 std::string color;
52
53 if (lvl == -1)
54 {
55 chart_area = std::string(",chartArea: {\
56 backgroundColor: {\
57 stroke: '#00FF00',\
58 strokeWidth: 6\
59 }\
60 }");
61 }
62 else if (lvl == 0)
63 {
64 // NOTHING TO DO
65 }
66 else if (lvl == 1)
67 {
68 chart_area = std::string(",chartArea: {\
69 backgroundColor: {\
70 stroke: '#FFFF00',\
71 strokeWidth: 6\
72 }\
73 }");
74 }
75 else if (lvl == 2)
76 {
77 chart_area = std::string(",chartArea: {\
78 backgroundColor: {\
79 stroke: '#FF0000',\
80 strokeWidth: 6\
81 }\
82 }");
83 }
84
85}
86
87/*! \brief Check of a string is a float
88 *
89 * \param something strign to check if it is a number
90 *
91 */
92static bool isFloat(const std::string &someString)
93{
94 using boost::lexical_cast;
95 using boost::bad_lexical_cast;
96
97 try
98 {boost::lexical_cast<float>(someString);}
99 catch (bad_lexical_cast &)
100 {return false;}
101
102 return true;
103}
104
105static void StandardXMLPerformanceGraph(std::string file_xml,
106 std::string file_xml_ref,
107 GoogleChart & cg,
108 const double deviationMultiplier = 3.0)
109{
110 // Create empty property tree object
111 boost::property_tree::ptree tree_measure;
112
113 // Parse the XML into the property tree.
114 boost::property_tree::read_xml(file_xml, tree_measure);
115
116 // Create empty property tree object
117 boost::property_tree::ptree tree_reference;
118
119 // We check if exist the reference file. If does not exist copy the file_xml into the report folder
120 if (boost::filesystem::exists(file_xml_ref) == false )
121 {
122 boost::filesystem::copy_file(file_xml,file_xml_ref);
123 }
124
125 // Parse the JSON into the property tree.
126 boost::property_tree::read_xml(file_xml_ref, tree_reference);
127
128 // First we check for graphs
129
130// try
131 {
132 boost::property_tree::ptree childs = tree_measure.get_child("graphs");
133
134 for (auto & c: childs)
135 {
136 std::string type = c.second.template get<std::string>("type","");
137 // discorver the number of points
138 int number = 0;
139 openfpm::vector<std::string> yn;
140
141 while (1)
142 {
143 if (c.second.template get<std::string>("y.data(" + std::to_string(number) + ").title","") == "")
144 {break;}
145 yn.add(c.second.template get<std::string>("y.data(" + std::to_string(number) + ").title",
146 "line" + std::to_string(number)));
147 yn.add("interval");
148 yn.add("interval");
149 number++;
150 }
151
152 bool is_log_x = c.second.template get<bool>("options.log_x",false);
153 bool is_log_y = c.second.template get<bool>("options.log_y",false);
154
155 // We process the graph
156 std::string title = c.second.template get<std::string>("title","");
157 std::string x_title = c.second.template get<std::string>("x.title","");
158 std::string y_title = c.second.template get<std::string>("y.title","");
159
160 // This is optional
161
162 std::string preHTML = c.second.template get<std::string>("preHTML","");
163 std::string postHTML = c.second.template get<std::string>("postHTML","");
164
165 openfpm::vector<openfpm::vector<double>> x;
166 openfpm::vector<openfpm::vector<std::string>> xs;
167 openfpm::vector<openfpm::vector<double>> y;
168
169 openfpm::vector<openfpm::vector<double>> x_ref;
170 openfpm::vector<openfpm::vector<double>> y_ref_up;
171 openfpm::vector<openfpm::vector<double>> y_ref_dw;
172
173 int warning_level = -1;
174 bool is_literal_x = false;
175
176 for (size_t i = 0 ; i < number ; i++)
177 {
178 x.add();
179 xs.add();
180 y.add();
181
182 x_ref.add();
183 y_ref_up.add();
184 y_ref_dw.add();
185
186 std::string xv = c.second.template get<std::string>("x.data(" + std::to_string(i) + ").source","");
187 std::string yv = c.second.template get<std::string>("y.data(" + std::to_string(i) + ").source","");
188
189 // Get the numbers
190
191 int j = 0;
192 while (1)
193 {
194 std::string xv_ = xv;
195 std::string yv_ = yv;
196
197 int xpos = xv_.find("#");
198 int ypos = yv_.find("#");
199
200 xv_.replace(xpos,1,std::to_string(j));
201 yv_.replace(ypos,1,std::to_string(j));
202
203 if (tree_measure.template get<std::string>(xv_,"") == "")
204 {
205 if (j == 0)
206 {
207 std::cout << "WARNING: Not found " << xv_ << " in file: " << file_xml << std::endl;
208 }
209 break;
210 }
211
212 std::string tmp = tree_measure.template get<std::string>(xv_,"");
213
214 double x_val;
215 std::string x_val_str;
216 if (isFloat(tmp) == true)
217 {x_val = tree_measure.template get<double>(xv_,0.0);}
218 else
219 {
220 is_literal_x = true;
221 xs.last().add(tmp);
222 }
223
224 double y_val = tree_measure.template get<double>(yv_,0.0);
225
226 double x_val_ref = tree_reference.template get<double>(xv_,0.0);
227 double y_val_ref = tree_reference.template get<double>(yv_,0.0);
228
229 if (y_val_ref == 0.0)
230 {
231 std::cout << "WARNING: " << yv_ << " does not exist on the reference file: " << file_xml_ref << std::endl;
232 }
233
234 ypos = yv_.find(".mean");
235 std::string yv_dev = yv_.replace(ypos,5,".dev");
236 double y_val_dev_ref = tree_reference.template get<double>(yv_,0.0);
237
238 if (y_val_dev_ref == 0.0)
239 {
240 std::cout << "WARNING: " << yv_ << " does not exist on the reference file: " << file_xml_ref << std::endl;
241 }
242
243 x.last().add(x_val);
244 y.last().add(y_val);
245
246 x_ref.last().add(x_val_ref);
247 y_ref_dw.last().add(y_val_ref - deviationMultiplier * y_val_dev_ref);
248 y_ref_up.last().add(y_val_ref + deviationMultiplier * y_val_dev_ref);
249
250 warning_set(warning_level,y_val,y_val_ref,y_val_dev_ref);
251
252 j++;
253 }
254 }
255
256 if (type == "line")
257 {
258 GCoptions opt;
259
260 std::string chart_area;
261 addchartarea(chart_area,warning_level);
262 opt.curveType = c.second.template get<std::string>("interpolation","function");
263// opt.curveType = c.second.template get<std::string>("interpolation","none");
264
265 if (is_log_x == true)
266 {
267 opt.more = GC_X_LOG + "," + GC_ZOOM + chart_area;
268 }
269 else
270 {
271 opt.more = GC_ZOOM + chart_area;
272 }
273
274 if (is_log_y == true)
275 {
276 opt.more = GC_Y_LOG + "," + GC_ZOOM + chart_area;
277 }
278 else
279 {
280 opt.more = GC_ZOOM + chart_area;
281 }
282
283 opt.title = title;
284 opt.xAxis = x_title;
285 opt.yAxis = y_title;
286
287 if (is_literal_x == false)
288 {
289 if (x.size() == 1)
290 {
291 cg.AddLines(yn,opt,x.get(0),y.get(0),
292 x_ref.get(0),y_ref_dw.get(0),
293 x_ref.get(0),y_ref_up.get(0));
294 }
295 if (x.size() == 2)
296 {
297 cg.AddLines(yn,opt,x.get(0),y.get(0),
298 x_ref.get(0),y_ref_dw.get(0),x_ref.get(0),y_ref_up.get(0),
299 x.get(1),y.get(1),
300 x_ref.get(1),y_ref_dw.get(1),x_ref.get(1),y_ref_up.get(1));
301 }
302 if (x.size() == 3)
303 {
304 cg.AddLines(yn,opt,x.get(0),y.get(0),
305 x_ref.get(0),y_ref_dw.get(0),x_ref.get(0),y_ref_up.get(0),
306 x.get(1),y.get(1),
307 x_ref.get(1),y_ref_dw.get(1),x_ref.get(1),y_ref_up.get(1),
308 x.get(2),y.get(2),
309 x_ref.get(2),y_ref_dw.get(2),x_ref.get(2),y_ref_up.get(2));
310 }
311 if (x.size() == 4)
312 {
313 cg.AddLines(yn,opt,x.get(0),y.get(0),
314 x_ref.get(0),y_ref_dw.get(0),x_ref.get(0),y_ref_up.get(0),
315 x.get(1),y.get(1),
316 x_ref.get(1),y_ref_dw.get(1),x_ref.get(1),y_ref_up.get(1),
317 x.get(2),y.get(2),
318 x_ref.get(2),y_ref_dw.get(2),x_ref.get(2),y_ref_up.get(2),
319 x.get(3),y.get(3),
320 x_ref.get(3),y_ref_dw.get(3),x_ref.get(3),y_ref_up.get(3));
321 }
322 if (x.size() == 5)
323 {
324 cg.AddLines(yn,opt,x.get(0),y.get(0),
325 x_ref.get(0),y_ref_dw.get(0),x_ref.get(0),y_ref_up.get(0),
326 x.get(1),y.get(1),
327 x_ref.get(1),y_ref_dw.get(1),x_ref.get(1),y_ref_up.get(1),
328 x.get(2),y.get(2),
329 x_ref.get(2),y_ref_dw.get(2),x_ref.get(2),y_ref_up.get(2),
330 x.get(3),y.get(3),
331 x_ref.get(3),y_ref_dw.get(3),x_ref.get(3),y_ref_up.get(3),
332 x.get(4),y.get(4),
333 x_ref.get(4),y_ref_dw.get(4),x_ref.get(4),y_ref_up.get(4));
334 }
335 if (x.size() == 6)
336 {
337 cg.AddLines(yn,opt,x.get(0),y.get(0),
338 x_ref.get(0),y_ref_dw.get(0),x_ref.get(0),y_ref_up.get(0),
339 x.get(1),y.get(1),
340 x_ref.get(1),y_ref_dw.get(1),x_ref.get(1),y_ref_up.get(1),
341 x.get(2),y.get(2),
342 x_ref.get(2),y_ref_dw.get(2),x_ref.get(2),y_ref_up.get(2),
343 x.get(3),y.get(3),
344 x_ref.get(3),y_ref_dw.get(3),x_ref.get(3),y_ref_up.get(3),
345 x.get(4),y.get(4),
346 x_ref.get(4),y_ref_dw.get(4),x_ref.get(4),y_ref_up.get(4),
347 x.get(5),y.get(5),
348 x_ref.get(5),y_ref_dw.get(5),x_ref.get(5),y_ref_up.get(5));
349 }
350 }
351 else
352 {
353 openfpm::vector<openfpm::vector<double>> y_tmp;
354
355 y_tmp.resize(x.get(0).size());
356
357 for (size_t i = 0 ; i < x.size() ; i++)
358 {
359 for (size_t j = 0 ; j < x.get(i).size() ; j++)
360 {
361 y_tmp.get(j).add(y.get(i).get(j));
362 y_tmp.get(j).add(y_ref_dw.get(i).get(j));
363 y_tmp.get(j).add(y_ref_up.get(i).get(j));
364 }
365 }
366
367 cg.AddLinesGraph(xs.get(0),y_tmp,yn,opt);
368 }
369 }
370 }
371 }
372// catch (std::exception e)
373// {
374// std::cout << __FILE__ << ":" << __LINE__ << " Error: invalid xml for performance test " << e.what() << std::endl;
375// }
376
377}
378
379
380#endif /* PERFORMANCE_UTIL_HPP_ */
381