$extrastylesheet
perf_log.h
Go to the documentation of this file.
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