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