LR-splines  0.5
Profiler.cpp
Go to the documentation of this file.
00001 // $Id: Profiler.C 1013 2011-05-26 14:39:16Z kmo $
00002 //==============================================================================
00012 //==============================================================================
00013 
00014 #include "LRSpline/Profiler.h"
00015 #include <sys/time.h>
00016 
00017 namespace LR {
00018 
00019 Profiler* utl::profiler = 0;
00020 
00021 
00022 Profiler::Profiler (const std::string& name) : myName(name), nRunners(0)
00023 {
00024   this->start("Total");
00025 
00026   allCPU = allWall = 0.0;
00027 
00028   // Update pointer to current profiler (it should only be one at any time)
00029   if (utl::profiler) delete utl::profiler;
00030   utl::profiler = this;
00031 }
00032 
00033 
00034 Profiler::~Profiler ()
00035 {
00036   this->stop("Total");
00037   this->report(std::cout);
00038 }
00039 
00040 
00042 
00043 static double WallTime ()
00044 {
00045   timeval tmpTime;
00046   gettimeofday(&tmpTime,NULL);
00047   return tmpTime.tv_sec + tmpTime.tv_usec/1.0e6;
00048 }
00049 
00050 
00051 void Profiler::start (const std::string& funcName)
00052 {
00053   Profile& p = myTimers[funcName];
00054   if (p.running) return;
00055 
00056   p.running = true;
00057   nRunners++;
00058   p.nCalls++;
00059   p.startWall = WallTime();
00060   p.startCPU = clock();
00061 }
00062 
00063 
00064 void Profiler::stop (const std::string& funcName)
00065 {
00066   clock_t stopCPU = clock();
00067   double stopWall = WallTime();
00068 
00069   std::map<std::string,Profile>::iterator it = myTimers.find(funcName);
00070   if (it == myTimers.end())
00071     std::cerr <<" *** No matching timer for "<< funcName << std::endl;
00072   else if (it->second.running)
00073   {
00074     // Accumulate consumed CPU and wall time by this task
00075     Profile& p = it->second;
00076     double deltaCPU  = double(stopCPU - p.startCPU)/double(CLOCKS_PER_SEC);
00077     double deltaWall = stopWall - p.startWall;
00078     p.running = false;
00079     p.totalCPU  += deltaCPU;
00080     p.totalWall += deltaWall;
00081     if (--nRunners == 1)
00082     {
00083       // This is a "main" task, accumulate the total time for all main tasks
00084       allCPU  += deltaCPU;
00085       allWall += deltaWall;
00086     }
00087   }
00088 }
00089 
00090 
00091 static bool use_ms = false; 
00092 
00093 
00095 
00096 std::ostream& operator<<(std::ostream& os, const Profiler::Profile& p)
00097 {
00098   // First the CPU time
00099   os.width(10);
00100   os << p.totalCPU;
00101   if (p.nCalls > 1)
00102   {
00103     os.width(9);
00104     os << (use_ms ? 1000.0 : 1.0)*p.totalCPU/p.nCalls <<" |";
00105   }
00106   else
00107     os <<"          |";
00108 
00109   // Then the wall time and the number of invokations (if more than one)
00110   os.width(10);
00111   os << p.totalWall;
00112   if (p.nCalls > 1)
00113   {
00114     os.width(9);
00115     os << (use_ms ? 1000.0 : 1.0)*p.totalWall/p.nCalls <<" |";
00116     os.width(6);
00117     os << p.nCalls;
00118   }
00119   else
00120     os <<"          |";
00121 
00122   return os <<'\n';
00123 }
00124 
00125 
00126 void Profiler::report (std::ostream& os) const
00127 {
00128   if (myTimers.empty()) return;
00129 
00130   use_ms = true; // Print mean times in microseconds by default
00131   std::map<std::string,Profile>::const_iterator it;
00132   for (it = myTimers.begin(); it != myTimers.end(); it++)
00133   {
00134     // Make sure the task has stopped profiling (in case of exceptions)
00135     if (it->second.running) const_cast<Profiler*>(this)->stop(it->first);
00136     if (it->second.nCalls > 1)
00137       if (it->second.totalWall/it->second.nCalls >= 100.0)
00138         use_ms = false; // Print mean times in seconds
00139   }
00140 
00141   // Find the time for "other" tasks, i.e., the difference between
00142   // the measured total time and the sum of all the measured tasks
00143   Profile other;
00144   std::map<std::string,Profile>::const_iterator tit = myTimers.find("Total");
00145   if (tit != myTimers.end())
00146   {
00147     if (!tit->second.haveTime()) return; // Nothing to report, run in zero time
00148     other.totalCPU  = tit->second.totalCPU  - allCPU;
00149     other.totalWall = tit->second.totalWall - allWall;
00150   }
00151 
00152   int myId = -1;
00153 
00154   // Print a table with timing results, all tasks with zero time are ommitted
00155   const char* Ms = (use_ms ? "Mean(ms)" : "Mean(s) ");
00156   os <<"\n==============================================================="
00157      <<"\n===   Profiling results for "<< myName;
00158   if (myId >= 0) os <<" on processor "<< myId;
00159   os <<"\n================================================================="
00160      <<"\n                      |       CPU time     |      Wall time     |"
00161      <<"\nTask                  |  Total(s)  "<<Ms<<"|  Total(s)  "<<Ms<<"| calls"
00162      <<"\n----------------------+--------------------+--------------------+------"
00163      <<"\n";
00164   os.precision(2);
00165   os.flags(std::ios::fixed|std::ios::right);
00166   for (it = myTimers.begin(); it != myTimers.end(); it++)
00167     if (it != tit && it->second.haveTime())
00168       if (it->first.size() >= 22)
00169         os << it->first.substr(0,22) <<'|'<< it->second;
00170       else
00171         os << it->first << std::string(22-it->first.size(),' ')
00172            <<'|'<< it->second;
00173 
00174   // Finally, print the "other" and "total" times
00175   if (other.haveTime())
00176     os <<"Other                 |"<< other;
00177   if (tit != myTimers.end())
00178     os <<"----------------------+--------------------+--------------------+------"
00179        <<"\nTotal time            |"<< tit->second;
00180   os <<"======================================================================="
00181      << std::endl;
00182 }
00183 
00184 } // end namespace LR