/* * Copyright 2012 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "TimerData.h" #include "BenchTimer.h" #include using namespace std; TimerData::TimerData(int maxNumTimings) : fMaxNumTimings(maxNumTimings) , fCurrTiming(0) , fWallTimes(maxNumTimings) , fTruncatedWallTimes(maxNumTimings) , fCpuTimes(maxNumTimings) , fTruncatedCpuTimes(maxNumTimings) , fGpuTimes(maxNumTimings){ } bool TimerData::appendTimes(BenchTimer* timer) { SkASSERT(timer != NULL); if (fCurrTiming >= fMaxNumTimings) { return false; } fWallTimes[fCurrTiming] = timer->fWall; fTruncatedWallTimes[fCurrTiming] = timer->fTruncatedWall; fCpuTimes[fCurrTiming] = timer->fCpu; fTruncatedCpuTimes[fCurrTiming] = timer->fTruncatedCpu; fGpuTimes[fCurrTiming] = timer->fGpu; ++fCurrTiming; return true; } SkString TimerData::getResult(const char* doubleFormat, Result result, const char *configName, uint32_t timerFlags, int itersPerTiming) { SkASSERT(itersPerTiming >= 1); if (!fCurrTiming) { return SkString(""); } int numTimings = fCurrTiming; SkString wallStr(" msecs = "); SkString truncWallStr(" Wmsecs = "); SkString cpuStr(" cmsecs = "); SkString truncCpuStr(" Cmsecs = "); SkString gpuStr(" gmsecs = "); double wallMin = std::numeric_limits::max(); double truncWallMin = std::numeric_limits::max(); double cpuMin = std::numeric_limits::max(); double truncCpuMin = std::numeric_limits::max(); double gpuMin = std::numeric_limits::max(); double wallSum = 0; double truncWallSum = 0; double cpuSum = 0; double truncCpuSum = 0; double gpuSum = 0; for (int i = 0; i < numTimings; ++i) { if (kPerIter_Result == result) { wallStr.appendf(doubleFormat, fWallTimes[i] / itersPerTiming); truncWallStr.appendf(doubleFormat, fTruncatedWallTimes[i] / itersPerTiming); cpuStr.appendf(doubleFormat, fCpuTimes[i] / itersPerTiming); truncCpuStr.appendf(doubleFormat, fTruncatedCpuTimes[i] / itersPerTiming); gpuStr.appendf(doubleFormat, fGpuTimes[i] / itersPerTiming); if (i != numTimings - 1) { static const char kSep[] = ", "; wallStr.append(kSep); truncWallStr.append(kSep); cpuStr.append(kSep); truncCpuStr.append(kSep); gpuStr.append(kSep); } } else if (kMin_Result == result) { wallMin = SkTMin(wallMin, fWallTimes[i]); truncWallMin = SkTMin(truncWallMin, fTruncatedWallTimes[i]); cpuMin = SkTMin(cpuMin, fCpuTimes[i]); truncCpuMin = SkTMin(truncCpuMin, fTruncatedCpuTimes[i]); gpuMin = SkTMin(gpuMin, fGpuTimes[i]); } else { SkASSERT(kAvg_Result == result); wallSum += fWallTimes[i]; truncWallSum += fTruncatedWallTimes[i]; cpuSum += fCpuTimes[i]; truncCpuSum += fTruncatedCpuTimes[i]; } // We always track the GPU sum because whether it is non-zero indicates if valid gpu times // were recorded at all. gpuSum += fGpuTimes[i]; } if (kMin_Result == result) { wallStr.appendf(doubleFormat, wallMin / itersPerTiming); truncWallStr.appendf(doubleFormat, truncWallMin / itersPerTiming); cpuStr.appendf(doubleFormat, cpuMin / itersPerTiming); truncCpuStr.appendf(doubleFormat, truncCpuMin / itersPerTiming); gpuStr.appendf(doubleFormat, gpuMin / itersPerTiming); } else if (kAvg_Result == result) { int divisor = numTimings * itersPerTiming; wallStr.appendf(doubleFormat, wallSum / divisor); truncWallStr.appendf(doubleFormat, truncWallSum / divisor); cpuStr.appendf(doubleFormat, cpuSum / divisor); truncCpuStr.appendf(doubleFormat, truncCpuSum / divisor); gpuStr.appendf(doubleFormat, gpuSum / divisor); } SkString str; str.printf(" %4s:", configName); if (timerFlags & kWall_Flag) { str += wallStr; } if (timerFlags & kTruncatedWall_Flag) { str += truncWallStr; } if (timerFlags & kCpu_Flag) { str += cpuStr; } if (timerFlags & kTruncatedCpu_Flag) { str += truncCpuStr; } if ((timerFlags & kGpu_Flag) && gpuSum > 0) { str += gpuStr; } return str; } Json::Value TimerData::getJSON(uint32_t timerFlags, Result result, int itersPerTiming) { SkASSERT(itersPerTiming >= 1); Json::Value dataNode; Json::Value wallNode, truncWall, cpuNode, truncCpu, gpuNode; if (!fCurrTiming) { return dataNode; } int numTimings = fCurrTiming; double wallMin = std::numeric_limits::max(); double truncWallMin = std::numeric_limits::max(); double cpuMin = std::numeric_limits::max(); double truncCpuMin = std::numeric_limits::max(); double gpuMin = std::numeric_limits::max(); double wallSum = 0; double truncWallSum = 0; double cpuSum = 0; double truncCpuSum = 0; double gpuSum = 0; for (int i = 0; i < numTimings; ++i) { if (kPerIter_Result == result) { wallNode.append(fWallTimes[i] / itersPerTiming); truncWall.append(fTruncatedWallTimes[i] / itersPerTiming); cpuNode.append(fCpuTimes[i] / itersPerTiming); truncCpu.append(fTruncatedCpuTimes[i] / itersPerTiming); gpuNode.append(fGpuTimes[i] / itersPerTiming); } else if (kMin_Result == result) { wallMin = SkTMin(wallMin, fWallTimes[i]); truncWallMin = SkTMin(truncWallMin, fTruncatedWallTimes[i]); cpuMin = SkTMin(cpuMin, fCpuTimes[i]); truncCpuMin = SkTMin(truncCpuMin, fTruncatedCpuTimes[i]); gpuMin = SkTMin(gpuMin, fGpuTimes[i]); } else { SkASSERT(kAvg_Result == result); wallSum += fWallTimes[i]; truncWallSum += fTruncatedWallTimes[i]; cpuSum += fCpuTimes[i]; truncCpuSum += fTruncatedCpuTimes[i]; } // We always track the GPU sum because whether it is non-zero indicates if valid gpu times // were recorded at all. gpuSum += fGpuTimes[i]; } if (kMin_Result == result) { wallNode.append(wallMin / itersPerTiming); truncWall.append(truncWallMin / itersPerTiming); cpuNode.append(cpuMin / itersPerTiming); truncCpu.append(truncCpuMin / itersPerTiming); gpuNode.append(gpuMin / itersPerTiming); } else if (kAvg_Result == result) { int divisor = numTimings * itersPerTiming; wallNode.append(wallSum / divisor); truncWall.append(truncWallSum / divisor); cpuNode.append(cpuSum / divisor); truncCpu.append(truncCpuSum / divisor); gpuNode.append(gpuSum / divisor); } if (timerFlags & kWall_Flag) { dataNode["wall"] = wallNode; } if (timerFlags & kTruncatedWall_Flag) { dataNode["truncWall"] = truncWall; } if (timerFlags & kCpu_Flag) { dataNode["cpu"] = cpuNode; } if (timerFlags & kTruncatedCpu_Flag) { dataNode["trucCpu"] = truncCpu; } if ((timerFlags & kGpu_Flag) && gpuSum > 0) { dataNode["gpu"] = gpuNode; } return dataNode; }