| /* |
| * Copyright 2014 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| * |
| * Classes for writing out bench results in various formats. |
| */ |
| |
| #ifndef SkPictureResultsWriter_DEFINED |
| #define SkPictureResultsWriter_DEFINED |
| |
| #include "BenchLogger.h" |
| #include "ResultsWriter.h" |
| #include "SkJSONCPP.h" |
| #include "SkStream.h" |
| #include "SkString.h" |
| #include "SkTArray.h" |
| #include "TimerData.h" |
| |
| /** |
| * Base class for writing picture bench results. |
| */ |
| class PictureResultsWriter : SkNoncopyable { |
| public: |
| enum TileFlags {kPurging, kAvg}; |
| |
| PictureResultsWriter() {} |
| virtual ~PictureResultsWriter() {} |
| |
| virtual void bench(const char name[], int32_t x, int32_t y) = 0; |
| virtual void tileConfig(SkString configName) = 0; |
| virtual void tileMeta(int x, int y, int tx, int ty) = 0; |
| virtual void addTileFlag(PictureResultsWriter::TileFlags flag) = 0; |
| virtual void tileData( |
| TimerData* data, |
| const char format[], |
| const TimerData::Result result, |
| uint32_t timerTypes, |
| int numInnerLoops = 1) = 0; |
| virtual void end() = 0; |
| }; |
| |
| /** |
| * This class allows bench data to be piped into multiple |
| * PictureResultWriter classes. It does not own any classes |
| * passed to it, so the owner is required to manage any classes |
| * passed to PictureResultsMultiWriter */ |
| class PictureResultsMultiWriter : public PictureResultsWriter { |
| public: |
| PictureResultsMultiWriter() |
| : fWriters() {} |
| void add(PictureResultsWriter* newWriter) { |
| fWriters.push_back(newWriter); |
| } |
| virtual ~PictureResultsMultiWriter() {} |
| virtual void bench(const char name[], int32_t x, int32_t y) { |
| for(int i=0; i<fWriters.count(); ++i) { |
| fWriters[i]->bench(name, x, y); |
| } |
| } |
| virtual void tileConfig(SkString configName) { |
| for(int i=0; i<fWriters.count(); ++i) { |
| fWriters[i]->tileConfig(configName); |
| } |
| } |
| virtual void tileMeta(int x, int y, int tx, int ty) { |
| for(int i=0; i<fWriters.count(); ++i) { |
| fWriters[i]->tileMeta(x, y, tx, ty); |
| } |
| } |
| virtual void addTileFlag(PictureResultsWriter::TileFlags flag) { |
| for(int i=0; i<fWriters.count(); ++i) { |
| fWriters[i]->addTileFlag(flag); |
| } |
| } |
| virtual void tileData( |
| TimerData* data, |
| const char format[], |
| const TimerData::Result result, |
| uint32_t timerTypes, |
| int numInnerLoops = 1) { |
| for(int i=0; i<fWriters.count(); ++i) { |
| fWriters[i]->tileData(data, format, result, timerTypes, |
| numInnerLoops); |
| } |
| } |
| virtual void end() { |
| for(int i=0; i<fWriters.count(); ++i) { |
| fWriters[i]->end(); |
| } |
| } |
| private: |
| SkTArray<PictureResultsWriter*> fWriters; |
| }; |
| |
| /** |
| * Writes to BenchLogger to mimic original behavior |
| */ |
| class PictureResultsLoggerWriter : public PictureResultsWriter { |
| private: |
| void logProgress(const char str[]) { |
| if(fLogger != NULL) { |
| fLogger->logProgress(str); |
| } |
| } |
| public: |
| PictureResultsLoggerWriter(BenchLogger* log) |
| : fLogger(log), currentLine() {} |
| virtual void bench(const char name[], int32_t x, int32_t y) { |
| SkString result; |
| result.printf("running bench [%i %i] %s ", x, y, name); |
| this->logProgress(result.c_str()); |
| } |
| virtual void tileConfig(SkString configName) { |
| currentLine = configName; |
| } |
| virtual void tileMeta(int x, int y, int tx, int ty) { |
| currentLine.appendf(": tile [%i,%i] out of [%i,%i]", x, y, tx, ty); |
| } |
| virtual void addTileFlag(PictureResultsWriter::TileFlags flag) { |
| if(flag == PictureResultsWriter::kPurging) { |
| currentLine.append(" <withPurging>"); |
| } else if(flag == PictureResultsWriter::kAvg) { |
| currentLine.append(" <averaged>"); |
| } |
| } |
| virtual void tileData( |
| TimerData* data, |
| const char format[], |
| const TimerData::Result result, |
| uint32_t timerTypes, |
| int numInnerLoops = 1) { |
| SkString results = data->getResult(format, result, |
| currentLine.c_str(), timerTypes, numInnerLoops); |
| results.append("\n"); |
| this->logProgress(results.c_str()); |
| } |
| virtual void end() {} |
| private: |
| BenchLogger* fLogger; |
| SkString currentLine; |
| }; |
| |
| /** |
| * This PictureResultsWriter collects data in a JSON node |
| * |
| * The format is something like |
| * { |
| * benches: [ |
| * { |
| * name: "Name_of_test" |
| * tilesets: [ |
| * { |
| * name: "Name of the configuration" |
| * tiles: [ |
| * { |
| * flags: { |
| * purging: true //Flags for the current tile |
| * // are put here |
| * } |
| * data: { |
| * wsecs: [....] //Actual data ends up here |
| * } |
| * } |
| * ] |
| * } |
| * ] |
| * } |
| * ] |
| * }*/ |
| |
| class PictureJSONResultsWriter : public PictureResultsWriter { |
| public: |
| PictureJSONResultsWriter(const char filename[]) |
| : fFilename(filename), |
| fRoot(), |
| fCurrentBench(NULL), |
| fCurrentTileSet(NULL), |
| fCurrentTile(NULL) {} |
| |
| virtual void bench(const char name[], int32_t x, int32_t y) { |
| SkString sk_name(name); |
| sk_name.append("_"); |
| sk_name.appendS32(x); |
| sk_name.append("_"); |
| sk_name.appendS32(y); |
| Json::Value* bench_node = SkFindNamedNode(&fRoot["benches"], sk_name.c_str()); |
| fCurrentBench = &(*bench_node)["tileSets"]; |
| } |
| virtual void tileConfig(SkString configName) { |
| SkASSERT(fCurrentBench != NULL); |
| fCurrentTileSet = SkFindNamedNode(fCurrentBench, configName.c_str()); |
| fCurrentTile = &(*fCurrentTileSet)["tiles"][0]; |
| } |
| virtual void tileMeta(int x, int y, int tx, int ty) { |
| SkASSERT(fCurrentTileSet != NULL); |
| (*fCurrentTileSet)["tx"] = tx; |
| (*fCurrentTileSet)["ty"] = ty; |
| fCurrentTile = &(*fCurrentTileSet)["tiles"][x+tx*y]; |
| } |
| virtual void addTileFlag(PictureResultsWriter::TileFlags flag) { |
| SkASSERT(fCurrentTile != NULL); |
| if(flag == PictureResultsWriter::kPurging) { |
| (*fCurrentTile)["flags"]["purging"] = true; |
| } else if(flag == PictureResultsWriter::kAvg) { |
| (*fCurrentTile)["flags"]["averaged"] = true; |
| } |
| } |
| virtual void tileData( |
| TimerData* data, |
| const char format[], |
| const TimerData::Result result, |
| uint32_t timerTypes, |
| int numInnerLoops = 1) { |
| SkASSERT(fCurrentTile != NULL); |
| (*fCurrentTile)["data"] = data->getJSON(timerTypes, result, numInnerLoops); |
| } |
| virtual void end() { |
| SkFILEWStream stream(fFilename.c_str()); |
| stream.writeText(Json::FastWriter().write(fRoot).c_str()); |
| stream.flush(); |
| } |
| private: |
| SkString fFilename; |
| Json::Value fRoot; |
| Json::Value *fCurrentBench; |
| Json::Value *fCurrentTileSet; |
| Json::Value *fCurrentTile; |
| }; |
| |
| #endif |