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 unsigned int Profiler::infosOffset=((size_t)(&static_cast<ProfilerOfSize<1>*>(NULL)[1].infos))-((size_t)(&static_cast<ProfilerOfSize<1>*>(NULL)[1].prof));
00009
00010 ProfilerOfSize<20> * mainProfiler=NULL;
00011 ProfilerOfSize<06> * motionProfiler=NULL;
00012 ProfilerOfSize<06> * soundProfiler=NULL;
00013
00014
00015
00016
00017
00018 Profiler::Timer::Timer(unsigned int id, Profiler* prof) : _prof(prof), _id(id), _parent(-1U), _t(0L) {
00019 if(_prof!=NULL)
00020 _prof->setCurrent(*this);
00021 }
00022
00023 Profiler::Timer::~Timer() {
00024 if(_prof!=NULL)
00025 _prof->finished(*this);
00026 }
00027
00028 void Profiler::Timer::setID(unsigned int id, Profiler* prof) {
00029 _id=id;
00030 _prof=prof;
00031 if(_prof!=NULL)
00032 _prof->setCurrent(*this);
00033 }
00034
00035 Profiler::SectionInfo::SectionInfo()
00036 : totalTime(0L),lastTime(0L),totalInterval(0L),childTime(0L),execExpAvg(0),interExpAvg(0),calls(0)
00037 {
00038 name[0]='\0';
00039 for(unsigned int j=0; j<HistSize; j++)
00040 execHist[j]=interHist[j]=0;
00041 }
00042
00043 void Profiler::SectionInfo::reset() {
00044 totalTime.Set(0L);
00045 lastTime.Set();
00046 totalInterval.Set(0L);
00047 childTime.Set(0L);
00048 execExpAvg=0;
00049 interExpAvg=0;
00050 for(unsigned int j=0; j<HistSize; j++)
00051 execHist[j]=interHist[j]=0;
00052 calls=0;
00053 }
00054
00055 void Profiler::initBuckets() {
00056 float g=HistTime/pow(HistSize,HistCurve)/1000;
00057 for(unsigned int i=1; i<=HistSize; i++)
00058 buckets[i-1]=g*pow(i,HistCurve);
00059 }
00060
00061 unsigned int Profiler::getNewID(const char* name) {
00062 ASSERTRETVAL(sectionsUsed<maxSections,"Too many sections registered (increase ProfilerOfSize<MaxSections>)",-1U);
00063 SectionInfo * infos=getInfos();
00064 #ifdef DEBUG
00065 for(unsigned int i=0; i<sectionsUsed; i++)
00066 ASSERTRETVAL(strncmp(infos[i].name,name,MaxSectionNameLen-1)!=0,"Already using name " << name,-1U);
00067 #endif
00068 unsigned int id=sectionsUsed++;
00069 strncpy(infos[id].name,name,MaxSectionNameLen-1);
00070 infos[id].name[MaxSectionNameLen-1]='\0';
00071 return id;
00072 }
00073
00074 std::string Profiler::report() {
00075 char tmp[255];
00076 SectionInfo * infos=getInfos();
00077 sprintf(tmp,"Profiling information since: %f to %f\n",startTime.Value(),TimeET().Value());
00078 std::string ans(tmp);
00079 for(unsigned int i=0; i<sectionsUsed; i++) {
00080 sprintf(tmp,"%s:\n",infos[i].name); ans+=tmp;
00081 unsigned int calls=infos[i].calls;
00082 sprintf(tmp,"\t%d calls\n",calls); ans+=tmp;
00083 if(calls>0) {
00084 sprintf(tmp,"\t%f ms avg\n",infos[i].totalTime.Value()/calls*1000); ans+=tmp;
00085 sprintf(tmp,"\t%f ms exp.avg\n",infos[i].execExpAvg*1000); ans+=tmp;
00086 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;
00087 sprintf(tmp,"\t%f ms avg inter (%f fps)\n",infos[i].totalInterval.Value()/calls*1000,calls/infos[i].totalInterval.Value()); ans+=tmp;
00088 sprintf(tmp,"\t%f ms exp.avg (%f fps)\n",infos[i].interExpAvg*1000,1/infos[i].interExpAvg); ans+=tmp;
00089 ans+="\tExec: ";
00090 for(unsigned int j=0; j<HistSize; j++) {
00091 sprintf(tmp,"%d ",infos[i].execHist[j]);
00092 ans+=tmp;
00093 }
00094 ans+="\n\tInter: ";
00095 for(unsigned int j=0; j<HistSize; j++) {
00096 sprintf(tmp,"%d ",infos[i].interHist[j]);
00097 ans+=tmp;
00098 }
00099 ans+="\n";
00100 }
00101 }
00102 ans+="Bucket distribution (in ms):\n\t0";
00103 for(unsigned int j=0; j<HistSize; j++) {
00104 sprintf(tmp,"<%.3g, ",buckets[j]*1000);
00105 ans+=tmp;
00106 }
00107 ans+="\n";
00108 return ans;
00109 }
00110
00111 void Profiler::reset() {
00112 SectionInfo * infos=getInfos();
00113 for(unsigned int i=0; i<sectionsUsed; i++)
00114 infos[i].reset();
00115 startTime.Set();
00116 }
00117
00118 Profiler::Profiler(unsigned int mx)
00119 : curSection(-1U), startTime(), gamma(.85), maxSections(mx), sectionsUsed(0), autoInit()
00120 { }
00121
00122 unsigned int Profiler::AutoInit::refcount=0;
00123 unsigned int Profiler::AutoInit::totalcount=0;
00124
00125 Profiler::AutoInit::AutoInit() {
00126 if(totalcount==0)
00127 Profiler::initBuckets();
00128 totalcount++;
00129 refcount++;
00130 }
00131
00132 Profiler::AutoInit::~AutoInit() { refcount--; }
00133
00134 void Profiler::setCurrent(Timer& tr) {
00135 SectionInfo& info=getInfos()[tr._id];
00136 tr._parent=curSection;
00137 curSection=tr._id;
00138 info.calls++;
00139 if(info.calls>1) {
00140 TimeET diff=info.lastTime.Age();
00141 info.totalInterval+=diff;
00142 if(info.calls==2)
00143 info.interExpAvg=diff.Value();
00144 else
00145 info.interExpAvg=info.interExpAvg*gamma+(float)diff.Value()*(1-gamma);
00146 if(diff.Value()*1000>HistTime)
00147 info.interHist[HistSize-1]++;
00148 else
00149 info.interHist[getBucket(diff.Value())]++;
00150 }
00151 tr._t.Set();
00152 info.lastTime=tr._t;
00153 }
00154
00155 void Profiler::finished(Timer& tr) {
00156 TimeET diff=tr.elapsed();
00157 SectionInfo& info=getInfos()[tr._id];
00158 info.totalTime+=diff;
00159 if(tr._parent!=-1U)
00160 getInfos()[tr._parent].childTime+=diff;
00161
00162 if(info.calls==1)
00163 info.execExpAvg=diff.Value();
00164 else
00165 info.execExpAvg=info.execExpAvg*gamma+(float)diff.Value()*(1-gamma);
00166 if(diff.Value()*1000>HistTime)
00167 info.execHist[HistSize-1]++;
00168 else
00169 info.execHist[getBucket(diff.Value())]++;
00170
00171
00172 curSection=tr._parent;
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184