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