1 /*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 #include "TimerData.h"
8
9 #include "Timer.h"
10 #include <limits>
11
TimerData(int maxNumTimings)12 TimerData::TimerData(int maxNumTimings)
13 : fMaxNumTimings(maxNumTimings)
14 , fCurrTiming(0)
15 , fWallTimes(maxNumTimings)
16 , fTruncatedWallTimes(maxNumTimings)
17 , fCpuTimes(maxNumTimings)
18 , fTruncatedCpuTimes(maxNumTimings)
19 , fGpuTimes(maxNumTimings) {}
20
appendTimes(Timer * timer)21 bool TimerData::appendTimes(Timer* timer) {
22 SkASSERT(timer != NULL);
23 if (fCurrTiming >= fMaxNumTimings) {
24 return false;
25 }
26
27 fWallTimes[fCurrTiming] = timer->fWall;
28 fTruncatedWallTimes[fCurrTiming] = timer->fTruncatedWall;
29 fCpuTimes[fCurrTiming] = timer->fCpu;
30 fTruncatedCpuTimes[fCurrTiming] = timer->fTruncatedCpu;
31 fGpuTimes[fCurrTiming] = timer->fGpu;
32
33 ++fCurrTiming;
34
35 return true;
36 }
37
getResult(const char * doubleFormat,Result result,const char * configName,uint32_t timerFlags,int itersPerTiming)38 SkString TimerData::getResult(const char* doubleFormat,
39 Result result,
40 const char *configName,
41 uint32_t timerFlags,
42 int itersPerTiming) {
43 SkASSERT(itersPerTiming >= 1);
44
45 if (!fCurrTiming) {
46 return SkString("");
47 }
48
49 int numTimings = fCurrTiming;
50
51 SkString wallStr(" msecs = ");
52 SkString truncWallStr(" Wmsecs = ");
53 SkString cpuStr(" cmsecs = ");
54 SkString truncCpuStr(" Cmsecs = ");
55 SkString gpuStr(" gmsecs = ");
56
57 double wallMin = std::numeric_limits<double>::max();
58 double truncWallMin = std::numeric_limits<double>::max();
59 double cpuMin = std::numeric_limits<double>::max();
60 double truncCpuMin = std::numeric_limits<double>::max();
61 double gpuMin = std::numeric_limits<double>::max();
62
63 double wallSum = 0;
64 double truncWallSum = 0;
65 double cpuSum = 0;
66 double truncCpuSum = 0;
67 double gpuSum = 0;
68
69 for (int i = 0; i < numTimings; ++i) {
70 if (kPerIter_Result == result) {
71 wallStr.appendf(doubleFormat, fWallTimes[i] / itersPerTiming);
72 truncWallStr.appendf(doubleFormat, fTruncatedWallTimes[i] / itersPerTiming);
73 cpuStr.appendf(doubleFormat, fCpuTimes[i] / itersPerTiming);
74 truncCpuStr.appendf(doubleFormat, fTruncatedCpuTimes[i] / itersPerTiming);
75 gpuStr.appendf(doubleFormat, fGpuTimes[i] / itersPerTiming);
76
77 if (i != numTimings - 1) {
78 static const char kSep[] = ", ";
79 wallStr.append(kSep);
80 truncWallStr.append(kSep);
81 cpuStr.append(kSep);
82 truncCpuStr.append(kSep);
83 gpuStr.append(kSep);
84 }
85 } else if (kMin_Result == result) {
86 wallMin = SkTMin(wallMin, fWallTimes[i]);
87 truncWallMin = SkTMin(truncWallMin, fTruncatedWallTimes[i]);
88 cpuMin = SkTMin(cpuMin, fCpuTimes[i]);
89 truncCpuMin = SkTMin(truncCpuMin, fTruncatedCpuTimes[i]);
90 gpuMin = SkTMin(gpuMin, fGpuTimes[i]);
91 } else {
92 SkASSERT(kAvg_Result == result);
93 wallSum += fWallTimes[i];
94 truncWallSum += fTruncatedWallTimes[i];
95 cpuSum += fCpuTimes[i];
96 truncCpuSum += fTruncatedCpuTimes[i];
97 }
98
99 // We always track the GPU sum because whether it is non-zero indicates if valid gpu times
100 // were recorded at all.
101 gpuSum += fGpuTimes[i];
102 }
103
104 if (kMin_Result == result) {
105 wallStr.appendf(doubleFormat, wallMin / itersPerTiming);
106 truncWallStr.appendf(doubleFormat, truncWallMin / itersPerTiming);
107 cpuStr.appendf(doubleFormat, cpuMin / itersPerTiming);
108 truncCpuStr.appendf(doubleFormat, truncCpuMin / itersPerTiming);
109 gpuStr.appendf(doubleFormat, gpuMin / itersPerTiming);
110 } else if (kAvg_Result == result) {
111 int divisor = numTimings * itersPerTiming;
112 wallStr.appendf(doubleFormat, wallSum / divisor);
113 truncWallStr.appendf(doubleFormat, truncWallSum / divisor);
114 cpuStr.appendf(doubleFormat, cpuSum / divisor);
115 truncCpuStr.appendf(doubleFormat, truncCpuSum / divisor);
116 gpuStr.appendf(doubleFormat, gpuSum / divisor);
117 }
118
119 SkString str;
120 str.printf(" %4s:", configName);
121 if (timerFlags & kWall_Flag) {
122 str += wallStr;
123 }
124 if (timerFlags & kTruncatedWall_Flag) {
125 str += truncWallStr;
126 }
127 if (timerFlags & kCpu_Flag) {
128 str += cpuStr;
129 }
130 if (timerFlags & kTruncatedCpu_Flag) {
131 str += truncCpuStr;
132 }
133 if ((timerFlags & kGpu_Flag) && gpuSum > 0) {
134 str += gpuStr;
135 }
136 return str;
137 }
138
getJSON(uint32_t timerFlags,Result result,int itersPerTiming)139 Json::Value TimerData::getJSON(uint32_t timerFlags,
140 Result result,
141 int itersPerTiming) {
142 SkASSERT(itersPerTiming >= 1);
143 Json::Value dataNode;
144 Json::Value wallNode, truncWall, cpuNode, truncCpu, gpuNode;
145 if (!fCurrTiming) {
146 return dataNode;
147 }
148
149 int numTimings = fCurrTiming;
150
151 double wallMin = std::numeric_limits<double>::max();
152 double truncWallMin = std::numeric_limits<double>::max();
153 double cpuMin = std::numeric_limits<double>::max();
154 double truncCpuMin = std::numeric_limits<double>::max();
155 double gpuMin = std::numeric_limits<double>::max();
156
157 double wallSum = 0;
158 double truncWallSum = 0;
159 double cpuSum = 0;
160 double truncCpuSum = 0;
161 double gpuSum = 0;
162
163 for (int i = 0; i < numTimings; ++i) {
164 if (kPerIter_Result == result) {
165 wallNode.append(fWallTimes[i] / itersPerTiming);
166 truncWall.append(fTruncatedWallTimes[i] / itersPerTiming);
167 cpuNode.append(fCpuTimes[i] / itersPerTiming);
168 truncCpu.append(fTruncatedCpuTimes[i] / itersPerTiming);
169 gpuNode.append(fGpuTimes[i] / itersPerTiming);
170 } else if (kMin_Result == result) {
171 wallMin = SkTMin(wallMin, fWallTimes[i]);
172 truncWallMin = SkTMin(truncWallMin, fTruncatedWallTimes[i]);
173 cpuMin = SkTMin(cpuMin, fCpuTimes[i]);
174 truncCpuMin = SkTMin(truncCpuMin, fTruncatedCpuTimes[i]);
175 gpuMin = SkTMin(gpuMin, fGpuTimes[i]);
176 } else {
177 SkASSERT(kAvg_Result == result);
178 wallSum += fWallTimes[i];
179 truncWallSum += fTruncatedWallTimes[i];
180 cpuSum += fCpuTimes[i];
181 truncCpuSum += fTruncatedCpuTimes[i];
182 }
183
184 // We always track the GPU sum because whether it is non-zero indicates if valid gpu times
185 // were recorded at all.
186 gpuSum += fGpuTimes[i];
187 }
188
189 if (kMin_Result == result) {
190 wallNode.append(wallMin / itersPerTiming);
191 truncWall.append(truncWallMin / itersPerTiming);
192 cpuNode.append(cpuMin / itersPerTiming);
193 truncCpu.append(truncCpuMin / itersPerTiming);
194 gpuNode.append(gpuMin / itersPerTiming);
195 } else if (kAvg_Result == result) {
196 int divisor = numTimings * itersPerTiming;
197 wallNode.append(wallSum / divisor);
198 truncWall.append(truncWallSum / divisor);
199 cpuNode.append(cpuSum / divisor);
200 truncCpu.append(truncCpuSum / divisor);
201 gpuNode.append(gpuSum / divisor);
202 }
203
204 if (timerFlags & kWall_Flag) {
205 dataNode["wall"] = wallNode;
206 }
207 if (timerFlags & kTruncatedWall_Flag) {
208 dataNode["truncWall"] = truncWall;
209 }
210 if (timerFlags & kCpu_Flag) {
211 dataNode["cpu"] = cpuNode;
212 }
213 if (timerFlags & kTruncatedCpu_Flag) {
214 dataNode["trucCpu"] = truncCpu;
215 }
216 if ((timerFlags & kGpu_Flag) && gpuSum > 0) {
217 dataNode["gpu"] = gpuNode;
218 }
219 return dataNode;
220 }
221