| 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 | |
| 16 | static 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 | |
| 32 | static 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 | |
| 49 | static 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 | */ |
| 92 | static 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 | |
| 105 | static 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 | |