Home | History | Annotate | Download | only in tools
      1 /*
      2  * Copyright 2014 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  * Classes for writing out bench results in various formats.
      8  */
      9 
     10 #ifndef SkPictureResultsWriter_DEFINED
     11 #define SkPictureResultsWriter_DEFINED
     12 
     13 #include "BenchLogger.h"
     14 #include "ResultsWriter.h"
     15 #include "SkJSONCPP.h"
     16 #include "SkStream.h"
     17 #include "SkString.h"
     18 #include "SkTArray.h"
     19 #include "TimerData.h"
     20 
     21 /**
     22  * Base class for writing picture bench results.
     23  */
     24 class PictureResultsWriter : SkNoncopyable {
     25 public:
     26     enum TileFlags {kPurging, kAvg};
     27 
     28     PictureResultsWriter() {}
     29     virtual ~PictureResultsWriter() {}
     30 
     31     virtual void bench(const char name[], int32_t x, int32_t y) = 0;
     32     virtual void tileConfig(SkString configName) = 0;
     33     virtual void tileMeta(int x, int y, int tx, int ty) = 0;
     34     virtual void addTileFlag(PictureResultsWriter::TileFlags flag) = 0;
     35     virtual void tileData(
     36             TimerData* data,
     37             const char format[],
     38             const TimerData::Result result,
     39             uint32_t timerTypes,
     40             int numInnerLoops = 1) = 0;
     41    virtual void end() = 0;
     42 };
     43 
     44 /**
     45  * This class allows bench data to be piped into multiple
     46  * PictureResultWriter classes. It does not own any classes
     47  * passed to it, so the owner is required to manage any classes
     48  * passed to PictureResultsMultiWriter */
     49 class PictureResultsMultiWriter : public PictureResultsWriter {
     50 public:
     51     PictureResultsMultiWriter()
     52         : fWriters() {}
     53     void add(PictureResultsWriter* newWriter) {
     54         fWriters.push_back(newWriter);
     55     }
     56     virtual ~PictureResultsMultiWriter() {}
     57     virtual void bench(const char name[], int32_t x, int32_t y) {
     58         for(int i=0; i<fWriters.count(); ++i) {
     59             fWriters[i]->bench(name, x, y);
     60         }
     61     }
     62     virtual void tileConfig(SkString configName) {
     63         for(int i=0; i<fWriters.count(); ++i) {
     64             fWriters[i]->tileConfig(configName);
     65         }
     66     }
     67     virtual void tileMeta(int x, int y, int tx, int ty) {
     68         for(int i=0; i<fWriters.count(); ++i) {
     69             fWriters[i]->tileMeta(x, y, tx, ty);
     70         }
     71     }
     72     virtual void addTileFlag(PictureResultsWriter::TileFlags flag) {
     73         for(int i=0; i<fWriters.count(); ++i) {
     74             fWriters[i]->addTileFlag(flag);
     75         }
     76     }
     77     virtual void tileData(
     78             TimerData* data,
     79             const char format[],
     80             const TimerData::Result result,
     81             uint32_t timerTypes,
     82             int numInnerLoops = 1) {
     83         for(int i=0; i<fWriters.count(); ++i) {
     84             fWriters[i]->tileData(data, format, result, timerTypes,
     85                                  numInnerLoops);
     86         }
     87     }
     88    virtual void end() {
     89         for(int i=0; i<fWriters.count(); ++i) {
     90             fWriters[i]->end();
     91         }
     92    }
     93 private:
     94     SkTArray<PictureResultsWriter*> fWriters;
     95 };
     96 
     97 /**
     98  * Writes to BenchLogger to mimic original behavior
     99  */
    100 class PictureResultsLoggerWriter : public PictureResultsWriter {
    101 private:
    102     void logProgress(const char str[]) {
    103         if(fLogger != NULL) {
    104             fLogger->logProgress(str);
    105         }
    106     }
    107 public:
    108     PictureResultsLoggerWriter(BenchLogger* log)
    109           : fLogger(log), currentLine() {}
    110     virtual void bench(const char name[], int32_t x, int32_t y) {
    111         SkString result;
    112         result.printf("running bench [%i %i] %s ", x, y, name);
    113         this->logProgress(result.c_str());
    114     }
    115     virtual void tileConfig(SkString configName) {
    116         currentLine = configName;
    117     }
    118     virtual void tileMeta(int x, int y, int tx, int ty) {
    119         currentLine.appendf(": tile [%i,%i] out of [%i,%i]", x, y, tx, ty);
    120     }
    121     virtual void addTileFlag(PictureResultsWriter::TileFlags flag) {
    122         if(flag == PictureResultsWriter::kPurging) {
    123             currentLine.append(" <withPurging>");
    124         } else if(flag == PictureResultsWriter::kAvg) {
    125             currentLine.append(" <averaged>");
    126         }
    127     }
    128     virtual void tileData(
    129             TimerData* data,
    130             const char format[],
    131             const TimerData::Result result,
    132             uint32_t timerTypes,
    133             int numInnerLoops = 1) {
    134         SkString results = data->getResult(format, result,
    135                 currentLine.c_str(), timerTypes, numInnerLoops);
    136         results.append("\n");
    137         this->logProgress(results.c_str());
    138     }
    139     virtual void end() {}
    140 private:
    141     BenchLogger* fLogger;
    142     SkString currentLine;
    143 };
    144 
    145 /**
    146  * This PictureResultsWriter collects data in a JSON node
    147  *
    148  * The format is something like
    149  * {
    150  *      benches: [
    151  *          {
    152  *              name: "Name_of_test"
    153  *              tilesets: [
    154  *                  {
    155  *                      name: "Name of the configuration"
    156  *                      tiles: [
    157  *                          {
    158  *                              flags: {
    159  *                                  purging: true //Flags for the current tile
    160  *                                              // are put here
    161  *                              }
    162  *                              data: {
    163  *                                  wsecs: [....] //Actual data ends up here
    164  *                              }
    165  *                          }
    166  *                      ]
    167  *                  }
    168  *              ]
    169  *          }
    170  *      ]
    171  * }*/
    172 
    173 class PictureJSONResultsWriter : public PictureResultsWriter {
    174 public:
    175     PictureJSONResultsWriter(const char filename[])
    176         : fFilename(filename),
    177           fRoot(),
    178           fCurrentBench(NULL),
    179           fCurrentTileSet(NULL),
    180           fCurrentTile(NULL) {}
    181 
    182     virtual void bench(const char name[], int32_t x, int32_t y) {
    183         SkString sk_name(name);
    184         sk_name.append("_");
    185         sk_name.appendS32(x);
    186         sk_name.append("_");
    187         sk_name.appendS32(y);
    188         Json::Value* bench_node = SkFindNamedNode(&fRoot["benches"], sk_name.c_str());
    189         fCurrentBench = &(*bench_node)["tileSets"];
    190     }
    191     virtual void tileConfig(SkString configName) {
    192         SkASSERT(fCurrentBench != NULL);
    193         fCurrentTileSet = SkFindNamedNode(fCurrentBench, configName.c_str());
    194         fCurrentTile = &(*fCurrentTileSet)["tiles"][0];
    195     }
    196     virtual void tileMeta(int x, int y, int tx, int ty) {
    197         SkASSERT(fCurrentTileSet != NULL);
    198         (*fCurrentTileSet)["tx"] = tx;
    199         (*fCurrentTileSet)["ty"] = ty;
    200         fCurrentTile = &(*fCurrentTileSet)["tiles"][x+tx*y];
    201     }
    202     virtual void addTileFlag(PictureResultsWriter::TileFlags flag) {
    203         SkASSERT(fCurrentTile != NULL);
    204         if(flag == PictureResultsWriter::kPurging) {
    205             (*fCurrentTile)["flags"]["purging"] = true;
    206         } else if(flag == PictureResultsWriter::kAvg) {
    207             (*fCurrentTile)["flags"]["averaged"] = true;
    208         }
    209     }
    210     virtual void tileData(
    211             TimerData* data,
    212             const char format[],
    213             const TimerData::Result result,
    214             uint32_t timerTypes,
    215             int numInnerLoops = 1) {
    216         SkASSERT(fCurrentTile != NULL);
    217         (*fCurrentTile)["data"] = data->getJSON(timerTypes, result, numInnerLoops);
    218     }
    219     virtual void end() {
    220        SkFILEWStream stream(fFilename.c_str());
    221        stream.writeText(Json::FastWriter().write(fRoot).c_str());
    222        stream.flush();
    223     }
    224 private:
    225     SkString fFilename;
    226     Json::Value fRoot;
    227     Json::Value *fCurrentBench;
    228     Json::Value *fCurrentTileSet;
    229     Json::Value *fCurrentTile;
    230 };
    231 
    232 #endif
    233