| /* |
| * 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 "Timer.h" |
| #include <limits> |
| |
| TimerData::TimerData(int maxNumTimings) |
| : fMaxNumTimings(maxNumTimings) |
| , fCurrTiming(0) |
| , fWallTimes(maxNumTimings) |
| , fTruncatedWallTimes(maxNumTimings) |
| , fCpuTimes(maxNumTimings) |
| , fTruncatedCpuTimes(maxNumTimings) |
| , fGpuTimes(maxNumTimings) {} |
| |
| bool TimerData::appendTimes(Timer* 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<double>::max(); |
| double truncWallMin = std::numeric_limits<double>::max(); |
| double cpuMin = std::numeric_limits<double>::max(); |
| double truncCpuMin = std::numeric_limits<double>::max(); |
| double gpuMin = std::numeric_limits<double>::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<double>::max(); |
| double truncWallMin = std::numeric_limits<double>::max(); |
| double cpuMin = std::numeric_limits<double>::max(); |
| double truncCpuMin = std::numeric_limits<double>::max(); |
| double gpuMin = std::numeric_limits<double>::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; |
| } |