* Add newlines at the end of files.
[matthijs/ABM2.git] / ABM2 / Engine / profiler.cpp
1 #include "engine.h"\r
2 #include "profiler.h"\r
3 \r
4 int CProfileSample::lastOpenedSample=-1;\r
5 int CProfileSample::openSampleCount=0;\r
6 CProfileSample::profileSample CProfileSample::samples[MAX_PROFILER_SAMPLES];\r
7 IProfilerOutputHandler *CProfileSample::outputHandler=0;\r
8 float CProfileSample::rootBegin=0.0f;\r
9 float CProfileSample::rootEnd=0.0f;\r
10 bool CProfileSample::bProfilerIsRunning=true;\r
11 \r
12 CProfileSample::CProfileSample(std::string sampleName)\r
13 {\r
14         if(!bProfilerIsRunning)return;\r
15         //find the sample\r
16         int i=0;\r
17         int storeIndex=-1;\r
18         for(i=0;i<MAX_PROFILER_SAMPLES;++i)\r
19         {\r
20                 if(!samples[i].bIsValid)\r
21                 {\r
22                         if(storeIndex<0)storeIndex=i;\r
23                 }else{\r
24                         if(samples[i].name==sampleName)\r
25                         {\r
26                                 //this is the sample we want\r
27                                 //check that it's not already open\r
28                                 assert(!samples[i].bIsOpen && "Tried to profile a sample which was already being profiled");\r
29                                 //first, store it's index\r
30                                 iSampleIndex=i;\r
31                                 //the parent sample is the last opened sample\r
32                                 iParentIndex=lastOpenedSample;\r
33                                 lastOpenedSample=i;\r
34                                 samples[i].parentCount=openSampleCount;\r
35                                 ++openSampleCount;\r
36                                 samples[i].bIsOpen=true;\r
37                                 ++samples[i].callCount;\r
38                                 samples[i].startTime=GetTime();\r
39                                 //if this has no parent, it must be the 'main loop' sample, so do the global timer\r
40                                 if(iParentIndex<0)rootBegin=samples[i].startTime;\r
41                                 return;\r
42                         }\r
43                 }\r
44         }\r
45         //we've not found it, so it must be a new sample\r
46         //use the storeIndex value to store the new sample\r
47         assert(storeIndex>=0 && "Profiler has run out of sample slots!");\r
48         samples[storeIndex].bIsValid=true;\r
49         samples[storeIndex].name=sampleName;\r
50         iSampleIndex=storeIndex;\r
51         iParentIndex=lastOpenedSample;\r
52         lastOpenedSample=storeIndex;\r
53         samples[i].parentCount=openSampleCount;\r
54         openSampleCount++;\r
55         samples[storeIndex].bIsOpen=true;\r
56         samples[storeIndex].callCount=1;\r
57 \r
58         samples[storeIndex].totalTime=0.0f;\r
59         samples[storeIndex].childTime=0.0f;\r
60         samples[storeIndex].startTime=GetTime();\r
61         if(iParentIndex<0)rootBegin=samples[storeIndex].startTime;\r
62 }\r
63 \r
64 CProfileSample::~CProfileSample()\r
65 {\r
66         if(!bProfilerIsRunning)return;\r
67         float fEndTime=GetTime();\r
68         //phew... ok, we're done timing\r
69         samples[iSampleIndex].bIsOpen=false;\r
70         //calculate the time taken this profile, for ease of use later on\r
71         float fTimeTaken = fEndTime - samples[iSampleIndex].startTime;\r
72 \r
73         if(iParentIndex>=0)\r
74         {\r
75                 samples[iParentIndex].childTime+=fTimeTaken;\r
76         }else{\r
77                 //no parent, so this is the end of the main loop sample\r
78                 rootEnd=fEndTime;\r
79         }\r
80         samples[iSampleIndex].totalTime+=fTimeTaken;\r
81         lastOpenedSample=iParentIndex;\r
82         --openSampleCount;\r
83 }\r
84 \r
85 void CProfileSample::Output()\r
86 {\r
87         if(!bProfilerIsRunning)return;\r
88 \r
89         assert(outputHandler && "Profiler has no output handler set");\r
90         \r
91         outputHandler->BeginOutput(rootEnd-rootBegin);\r
92 \r
93         for(int i=0;i<MAX_PROFILER_SAMPLES; ++i)\r
94         {\r
95                 if(samples[i].bIsValid)\r
96                 {\r
97                         float sampleTime, percentage;\r
98                         //calculate the time spend on the sample itself (excluding children)\r
99                         sampleTime = samples[i].totalTime-samples[i].childTime;\r
100                         percentage = ( sampleTime / ( rootEnd - rootBegin ) ) * 100.0f;\r
101 \r
102                         //add it to the sample's values\r
103                         float totalPc;\r
104                         totalPc=samples[i].averagePc*samples[i].dataCount;\r
105                         totalPc+=percentage; samples[i].dataCount++;\r
106                         samples[i].averagePc=totalPc/samples[i].dataCount;\r
107                         if((samples[i].minPc==-1)||(percentage<samples[i].minPc))samples[i].minPc=percentage;\r
108                         if((samples[i].maxPc==-1)||(percentage>samples[i].maxPc))samples[i].maxPc=percentage;\r
109 \r
110                         //output these values\r
111                         outputHandler->Sample(samples[i].minPc,\r
112                                               samples[i].averagePc,\r
113                                               samples[i].maxPc,\r
114                                               sampleTime,\r
115                                               samples[i].callCount,\r
116                                               samples[i].name,\r
117                                               samples[i].parentCount);\r
118 \r
119                         //reset the sample for next time\r
120                         samples[i].callCount=0;\r
121                         samples[i].totalTime=0;\r
122                         samples[i].childTime=0;\r
123                 }\r
124         }\r
125 \r
126         outputHandler->EndOutput();\r
127 }\r
128 \r
129 void CProfileSample::ResetSample(std::string strName)\r
130 {\r
131         for(int i=0;i<MAX_PROFILER_SAMPLES; ++i)\r
132         {\r
133                 if((samples[i].bIsValid)&&(samples[i].name==strName))\r
134                 {\r
135                         //found it\r
136                         //reset avg/min/max ONLY\r
137                         //because the sample may be running\r
138                         samples[i].maxPc=samples[i].minPc=-1;\r
139                         samples[i].dataCount=0;\r
140                         return;\r
141                 }\r
142         }\r
143 }       \r
144 \r
145 void CProfileSample::ResetAll()\r
146 {\r
147         for(int i=0;i<MAX_PROFILER_SAMPLES;++i)\r
148         {\r
149                 if(samples[i].bIsValid)\r
150                 {\r
151                         samples[i].maxPc=samples[i].minPc=-1;\r
152                         samples[i].dataCount=0;\r
153                 }\r
154         }\r
155 }\r