$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 #ifndef LIBMESH_PERFLOG_H 00021 #define LIBMESH_PERFLOG_H 00022 00023 00024 // Local includes 00025 #include "libmesh/libmesh_common.h" 00026 00027 // C++ includes 00028 #include <cstddef> 00029 #include <map> 00030 #include <stack> 00031 #include <string> 00032 #include <vector> 00033 #include <sys/time.h> 00034 00035 namespace libMesh 00036 { 00037 00043 // ------------------------------------------------------------ 00044 // PerfData class definition 00045 class PerfData 00046 { 00047 public: 00048 00052 PerfData () : 00053 tot_time(0.), 00054 tot_time_incl_sub(0.), 00055 tstart(), 00056 tstart_incl_sub(), 00057 count(0), 00058 open(false), 00059 called_recursively(0) 00060 {} 00061 00062 00066 double tot_time; 00067 00071 double tot_time_incl_sub; 00072 00077 struct timeval tstart; 00078 00083 struct timeval tstart_incl_sub; 00084 00089 unsigned int count; 00090 00096 bool open; 00097 00098 void start (); 00099 void restart (); 00100 double pause (); 00101 double stopit (); 00102 00103 int called_recursively; 00104 00105 protected: 00106 double stop_or_pause(const bool do_stop); 00107 }; 00108 00109 00110 00111 00121 // ------------------------------------------------------------ 00122 // PerfLog class definition 00123 class PerfLog 00124 { 00125 00126 public: 00127 00135 PerfLog(const std::string& label_name="", 00136 const bool log_events=true); 00137 00141 ~PerfLog(); 00142 00150 void clear(); 00151 00155 void disable_logging() { log_events = false; } 00156 00160 void enable_logging() { log_events = true; } 00161 00165 bool logging_enabled() const { return log_events; } 00166 00170 void push (const char *label, 00171 const char *header=""); 00172 00176 void push (const std::string &label, 00177 const std::string &header=""); 00178 00182 void pop (const char *label, 00183 const char *header=""); 00184 00188 void pop (const std::string &label, 00189 const std::string &header=""); 00190 00194 void start_event(const std::string &label, 00195 const std::string &header=""); 00196 00200 void stop_event(const std::string &label, 00201 const std::string &header=""); 00202 00206 void pause_event(const std::string &label, 00207 const std::string &header=""); 00208 00212 void restart_event(const std::string &label, 00213 const std::string &header=""); 00214 00220 std::string get_log() const; 00221 00225 std::string get_info_header() const; 00226 00230 std::string get_perf_info() const; 00231 00235 void print_log() const; 00236 00240 double get_elapsed_time() const; 00241 00245 double get_active_time() const; 00246 00250 PerfData get_perf_data(const std::string &label, const std::string &header=""); 00251 00252 private: 00253 00254 00258 const std::string label_name; 00259 00263 bool log_events; 00264 00268 double total_time; 00269 00273 struct timeval tstart; 00274 00278 std::map<std::pair<std::string, 00279 std::string>, 00280 PerfData> log; 00281 00285 std::stack<PerfData*> log_stack; 00286 00292 static bool called; 00293 00298 void split_on_whitespace(const std::string& input, 00299 std::vector<std::string>& output) const; 00300 }; 00301 00302 00303 00304 // ------------------------------------------------------------ 00305 // PerfData class member funcions 00306 inline 00307 void PerfData::start () 00308 { 00309 this->count++; 00310 this->called_recursively++; 00311 gettimeofday (&(this->tstart), NULL); 00312 this->tstart_incl_sub = this->tstart; 00313 } 00314 00315 00316 00317 inline 00318 void PerfData::restart () 00319 { 00320 gettimeofday (&(this->tstart), NULL); 00321 } 00322 00323 00324 00325 inline 00326 double PerfData::pause () 00327 { 00328 return this->stop_or_pause(false); 00329 } 00330 00331 00332 inline 00333 double PerfData::stop_or_pause(const bool do_stop) 00334 { 00335 // save the start times, reuse the structure we have rather than create 00336 // a new one. 00337 const time_t 00338 tstart_tv_sec = this->tstart.tv_sec, 00339 tstart_tv_usec = this->tstart.tv_usec; 00340 00341 gettimeofday (&(this->tstart), NULL); 00342 00343 const double elapsed_time = (static_cast<double>(this->tstart.tv_sec - tstart_tv_sec) + 00344 static_cast<double>(this->tstart.tv_usec - tstart_tv_usec)*1.e-6); 00345 00346 this->tot_time += elapsed_time; 00347 00348 if(do_stop) 00349 { 00350 const double elapsed_time_incl_sub = (static_cast<double>(this->tstart.tv_sec - this->tstart_incl_sub.tv_sec) + 00351 static_cast<double>(this->tstart.tv_usec - this->tstart_incl_sub.tv_usec)*1.e-6); 00352 00353 this->tot_time_incl_sub += elapsed_time_incl_sub; 00354 } 00355 00356 return elapsed_time; 00357 } 00358 00359 00360 00361 inline 00362 double PerfData::stopit () 00363 { 00364 // stopit is just similar to pause except that it decrements the 00365 // recursive call counter 00366 00367 this->called_recursively--; 00368 return this->stop_or_pause(true); 00369 } 00370 00371 00372 00373 // ------------------------------------------------------------ 00374 // PerfLog class inline member funcions 00375 inline 00376 void PerfLog::push (const std::string &label, 00377 const std::string &header) 00378 { 00379 if (this->log_events) 00380 { 00381 // Get a reference to the event data to avoid 00382 // repeated map lookups 00383 PerfData *perf_data = &(log[std::make_pair(header,label)]); 00384 00385 if (!log_stack.empty()) 00386 total_time += 00387 log_stack.top()->pause(); 00388 00389 perf_data->start(); 00390 log_stack.push(perf_data); 00391 } 00392 } 00393 00394 00395 00396 inline 00397 void PerfLog::push (const char *label, 00398 const char *header) 00399 { 00400 if (this->log_events) 00401 this->push(std::string(label), std::string(header)); 00402 } 00403 00404 00405 00406 inline 00407 void PerfLog::pop (const std::string &libmesh_dbg_var(label), 00408 const std::string &libmesh_dbg_var(header)) 00409 { 00410 if (this->log_events) 00411 { 00412 libmesh_assert (!log_stack.empty()); 00413 00414 #ifndef NDEBUG 00415 PerfData *perf_data = &(log[std::make_pair(header,label)]); 00416 if (perf_data != log_stack.top()) 00417 { 00418 libMesh::err << "PerfLog can't pop (" << header << ',' << label << ')' << std::endl; 00419 libMesh::err << "From top of stack of running logs:" << std::endl; 00420 std::map<std::pair<std::string, std::string>, PerfData>::iterator 00421 i = log.begin(), endi = log.end(); 00422 for (; i != endi; ++i) 00423 if (&(i->second) == log_stack.top()) 00424 libMesh::err << '(' << i->first.first << ',' << i->first.second << ')' << std::endl; 00425 00426 libmesh_assert_equal_to (perf_data, log_stack.top()); 00427 } 00428 #endif 00429 00430 total_time += log_stack.top()->stopit(); 00431 00432 log_stack.pop(); 00433 00434 if (!log_stack.empty()) 00435 log_stack.top()->restart(); 00436 } 00437 } 00438 00439 00440 00441 inline 00442 void PerfLog::pop(const char *label, 00443 const char *header) 00444 { 00445 if (this->log_events) 00446 this->pop(std::string(label), std::string(header)); 00447 } 00448 00449 00450 00451 inline 00452 double PerfLog::get_elapsed_time () const 00453 { 00454 struct timeval tnow; 00455 00456 gettimeofday (&tnow, NULL); 00457 00458 const double elapsed_time = (static_cast<double>(tnow.tv_sec - tstart.tv_sec) + 00459 static_cast<double>(tnow.tv_usec - tstart.tv_usec)*1.e-6); 00460 return elapsed_time; 00461 } 00462 00463 inline 00464 double PerfLog::get_active_time() const 00465 { 00466 return total_time; 00467 } 00468 00469 } // namespace libMesh 00470 00471 00472 00473 #endif // LIBMESH_PERFLOG_H