Home | History | Annotate | Download | only in timer
      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 
     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 
     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 
     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 
    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