Homepage Demos Overview Downloads Tutorials Reference
Credits

Profiler.cc

Go to the documentation of this file.
00001 #include "Profiler.h"
00002 #include "debuget.h"
00003 
00004 const float Profiler::HistCurve = 4.05;
00005 
00006 float Profiler::buckets[Profiler::HistSize];
00007 
00008 #warning Note: Ignore warning on next line (sorry!)
00009 unsigned int Profiler::infosOffset=offsetof(ProfilerOfSize<1>,infos); //(unsigned int)(static_cast<ProfilerOfSize<1>*>(NULL)->infos);
00010 
00011 /*! Tells the profiler that this is now the active timer, so new timers will fit "under" this.\n
00012  *  Timer isn't actually started here, lets Profiler::setCurrent do that.
00013  *  @param prof profiler to report results to.  If is NULL, does nothing.
00014  *  @param id id number for this function.  See Profiler::getNewID() for what you should pass this */
00015 Profiler::Timer::Timer(unsigned int id, Profiler* prof) : _prof(prof), _id(id), _parent(-1U), _t(0L) {
00016   if(_prof!=NULL)
00017     _prof->setCurrent(*this);
00018 }
00019 
00020 Profiler::Timer::~Timer() {
00021   if(_prof!=NULL)
00022     _prof->finished(*this);
00023 }
00024 
00025 void Profiler::Timer::setID(unsigned int id, Profiler* prof) {
00026   _id=id;
00027   _prof=prof;
00028   if(_prof!=NULL)
00029     _prof->setCurrent(*this);
00030 } 
00031 
00032 Profiler::SectionInfo::SectionInfo()
00033   : totalTime(0L),lastTime(0L),totalInterval(0L),childTime(0L),execExpAvg(0),interExpAvg(0),calls(0)
00034 {
00035   name[0]='\0';
00036   for(unsigned int j=0; j<HistSize; j++)
00037     execHist[j]=interHist[j]=0;
00038 }
00039 
00040 void Profiler::SectionInfo::reset() {
00041   totalTime.Set(0L);
00042   lastTime.Set();
00043   totalInterval.Set(0L);
00044   childTime.Set(0L);
00045   execExpAvg=0;
00046   interExpAvg=0;
00047   for(unsigned int j=0; j<HistSize; j++)
00048     execHist[j]=interHist[j]=0;
00049   calls=0;
00050 }
00051 
00052 void Profiler::initBuckets() {
00053   float g=HistTime/pow(HistSize,HistCurve)/1000;
00054   for(unsigned int i=1; i<=HistSize; i++)
00055     buckets[i-1]=g*pow(i,HistCurve);
00056 }
00057 
00058 unsigned int Profiler::getNewID(const char* name) {
00059   ASSERTRETVAL(sectionsUsed<maxSections,"Too many sections registered (increase ProfilerOfSize<MaxSections>)",-1U);
00060   SectionInfo * infos=getInfos();
00061 #ifdef DEBUG
00062   for(unsigned int i=0; i<sectionsUsed; i++)
00063     ASSERTRETVAL(strncmp(infos[i].name,name,MaxSectionNameLen-1)!=0,"Already using name " << name,-1U);
00064 #endif
00065   unsigned int id=sectionsUsed++;
00066   strncpy(infos[id].name,name,MaxSectionNameLen-1);
00067   infos[id].name[MaxSectionNameLen-1]='\0'; //guarantees null-termination
00068   return id;
00069 }
00070 
00071 std::string Profiler::report() {
00072   char tmp[255];
00073   SectionInfo * infos=getInfos();
00074   sprintf(tmp,"Profiling information since: %f to %f\n",startTime.Value(),TimeET().Value());
00075   std::string ans(tmp);
00076   for(unsigned int i=0; i<sectionsUsed; i++) {
00077     sprintf(tmp,"%s:\n",infos[i].name); ans+=tmp;
00078     unsigned int calls=infos[i].calls;
00079     sprintf(tmp,"\t%d calls\n",calls); ans+=tmp;
00080     if(calls>0) {
00081       sprintf(tmp,"\t%f ms avg\n",infos[i].totalTime.Value()/calls*1000); ans+=tmp;
00082       sprintf(tmp,"\t%f ms exp.avg\n",infos[i].execExpAvg*1000); ans+=tmp;
00083       sprintf(tmp,"\t%f ms avg child time (%f%%)\n",infos[i].childTime.Value()/calls*1000,((int)(infos[i].childTime.Value()/infos[i].totalTime.Value()*1000))/10.0); ans+=tmp;
00084       sprintf(tmp,"\t%f ms avg inter (%f fps)\n",infos[i].totalInterval.Value()/calls*1000,calls/infos[i].totalInterval.Value()); ans+=tmp;
00085       sprintf(tmp,"\t%f ms exp.avg (%f fps)\n",infos[i].interExpAvg*1000,1/infos[i].interExpAvg); ans+=tmp;
00086       ans+="\tExec: ";
00087       for(unsigned int j=0; j<HistSize; j++) {
00088         sprintf(tmp,"%d ",infos[i].execHist[j]);
00089         ans+=tmp;
00090       }
00091       ans+="\n\tInter: ";
00092       for(unsigned int j=0; j<HistSize; j++) {
00093         sprintf(tmp,"%d ",infos[i].interHist[j]);
00094         ans+=tmp;
00095       }
00096       ans+="\n";
00097     }
00098   }
00099   ans+="Bucket distribution (in ms):\n\t0";
00100   for(unsigned int j=0; j<HistSize; j++) {
00101     sprintf(tmp,"<%.3g, ",buckets[j]*1000);
00102     ans+=tmp;
00103   }
00104   ans+="\n";
00105   return ans;
00106 }
00107 
00108 void Profiler::reset() {
00109   SectionInfo * infos=getInfos();
00110   for(unsigned int i=0; i<sectionsUsed; i++)
00111     infos[i].reset();
00112   startTime.Set();
00113 }
00114 
00115 Profiler::Profiler(unsigned int mx)
00116   : curSection(-1U), startTime(), gamma(.85), maxSections(mx), sectionsUsed(0)
00117 { }
00118 
00119 
00120 void Profiler::setCurrent(Timer& tr) {
00121   SectionInfo& info=getInfos()[tr._id];
00122   tr._parent=curSection;
00123   curSection=tr._id;
00124   info.calls++;
00125   if(info.calls>1) {
00126     TimeET diff=info.lastTime.Age();
00127     info.totalInterval+=diff;
00128     if(info.calls==2)
00129       info.interExpAvg=diff.Value();
00130     else
00131       info.interExpAvg=info.interExpAvg*gamma+(float)diff.Value()*(1-gamma);
00132     if(diff.Value()*1000>HistTime)
00133       info.interHist[HistSize-1]++;
00134     else
00135       info.interHist[getBucket(diff.Value())]++;
00136   }
00137   tr._t.Set(); //do last so profiling code won't throw off timing results (but makes childtime's a little bloated)
00138   info.lastTime=tr._t;
00139 }
00140 
00141 void Profiler::finished(Timer& tr) {
00142   TimeET diff=tr.elapsed(); //do immediately for accuracy
00143   SectionInfo& info=getInfos()[tr._id];
00144   info.totalTime+=diff;
00145   if(tr._parent!=-1U)
00146     getInfos()[tr._parent].childTime+=diff;
00147   //  ASSERT(info.calls!=0,"calls is 0 on finished");
00148   if(info.calls==1)
00149     info.execExpAvg=diff.Value();
00150   else
00151     info.execExpAvg=info.execExpAvg*gamma+(float)diff.Value()*(1-gamma);
00152   if(diff.Value()*1000>HistTime)
00153     info.execHist[HistSize-1]++;
00154   else
00155     info.execHist[getBucket(diff.Value())]++;
00156   //the old way:
00157   //info.execHist[mathutils::log2t((unsigned int)(((1U<<31)/HistTime*2)*diff.Value()))]++;
00158   curSection=tr._parent;
00159 }
00160 
00161 /*! @file
00162  * @brief Implements Profiler, which managers a hierarchy of timers for profiling time spent in code
00163  * @author ejt (Creator)
00164  *
00165  * $Author: ejt $
00166  * $Name: tekkotsu-2_2_1 $
00167  * $Revision: 1.13 $
00168  * $State: Exp $
00169  * $Date: 2004/03/25 17:08:57 $
00170  */

Tekkotsu v2.2.1
Generated Tue Nov 23 16:36:39 2004 by Doxygen 1.3.9.1