diff options
-rw-r--r-- | bench/ResultsWriter.h | 103 | ||||
-rw-r--r-- | bench/nanobench.cpp | 49 |
2 files changed, 143 insertions, 9 deletions
diff --git a/bench/ResultsWriter.h b/bench/ResultsWriter.h index 1ee3616ceb..dc45f192f5 100644 --- a/bench/ResultsWriter.h +++ b/bench/ResultsWriter.h @@ -26,6 +26,10 @@ class ResultsWriter : SkNoncopyable { public: virtual ~ResultsWriter() {}; + // Records one key value pair that makes up a unique identifier for this run. + // All keys must be set before calling bench(). + virtual void key(const char name[], const char value[]) = 0; + // Records one option set for this run. All options must be set before // calling bench(). virtual void option(const char name[], const char value[]) = 0; @@ -37,6 +41,9 @@ public: // Records the specific configuration a bench is run under, such as "8888". virtual void config(const char name[]) = 0; + // Records the options for a configuration, such as "GL_RENDERER". + virtual void configOption(const char name[], const char* value) = 0; + // Records a single test metric. virtual void timer(const char name[], double ms) = 0; @@ -55,6 +62,9 @@ public: , fTimeFormat(timeFormat) { fLogger.logProgress("skia bench:"); } + virtual void key(const char name[], const char value[]) { + // Don't log keys to keep microbench output unchanged. + } virtual void option(const char name[], const char value[]) { fLogger.logProgress(SkStringPrintf(" %s=%s", name, value)); } @@ -65,6 +75,9 @@ public: virtual void config(const char name[]) { fLogger.logProgress(SkStringPrintf(" %s:", name)); } + virtual void configOption(const char name[], const char* value) { + // Don't log configOptions to keep microbench output unchanged. + } virtual void timer(const char name[], double ms) { fLogger.logProgress(SkStringPrintf(" %s = ", name)); fLogger.logProgress(SkStringPrintf(fTimeFormat, ms)); @@ -113,6 +126,8 @@ public: , fBench(NULL) , fConfig(NULL) { } + virtual void key(const char name[], const char value[]) { + } virtual void option(const char name[], const char value[]) { fRoot["options"][name] = value; } @@ -129,7 +144,84 @@ public: SkASSERT(NULL != fBench); fConfig = SkFindNamedNode(fBench, name); } + virtual void configOption(const char name[], const char* value) { + } + virtual void timer(const char name[], double ms) { + SkASSERT(NULL != fConfig); + (*fConfig)[name] = ms; + } + 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& fResults; + Json::Value* fBench; + Json::Value* fConfig; +}; + +/** + NanoJSONResultsWriter writes the test results out in the following + format: + + { + "key": { + "arch": "Arm7", + "gpu": "SGX540", + "os": "Android", + "model": "GalaxyNexus", + } + "options": { + "GL_Version": "3.1", + ... + }, + "gitHash": "d1830323662ae8ae06908b97f15180fd25808894", + "results" : { + "Xfermode_Luminosity_640_480" : { + "8888" : { + "median_ms" : 143.188128906250, + "min_ms" : 143.835957031250, + ... + }, + ... +*/ +class NanoJSONResultsWriter : public ResultsWriter { +public: + explicit NanoJSONResultsWriter(const char filename[], const char gitHash[]) + : fFilename(filename) + , fRoot() + , fResults(fRoot["results"]) + , fBench(NULL) + , fConfig(NULL) { + fRoot["gitHash"] = gitHash; + } + virtual void key(const char name[], const char value[]) { + fRoot["key"][name] = value; + } + virtual void option(const char name[], const char value[]) { + fRoot["options"][name] = value; + } + virtual void bench(const char name[], int32_t x, int32_t y) { + SkString id = SkStringPrintf( "%s_%d_%d", name, x, y); + fResults[id.c_str()] = Json::Value(Json::objectValue); + fBench = &fResults[id.c_str()]; + } + virtual void config(const char name[]) { + SkASSERT(NULL != fBench); + fConfig = &(*fBench)[name]; + } + virtual void configOption(const char name[], const char* value) { + (*fConfig)["options"][name] = value; + } virtual void timer(const char name[], double ms) { + // Don't record if nan, or -nan. + if (sk_double_isnan(ms)) { + return; + } SkASSERT(NULL != fConfig); (*fConfig)[name] = ms; } @@ -147,6 +239,7 @@ private: Json::Value* fConfig; }; + /** * This ResultsWriter writes out to multiple ResultsWriters. */ @@ -157,6 +250,11 @@ public: void add(ResultsWriter* writer) { writers.push_back(writer); } + virtual void key(const char name[], const char value[]) { + for (int i = 0; i < writers.count(); ++i) { + writers[i]->key(name, value); + } + } virtual void option(const char name[], const char value[]) { for (int i = 0; i < writers.count(); ++i) { writers[i]->option(name, value); @@ -172,6 +270,11 @@ public: writers[i]->config(name); } } + virtual void configOption(const char name[], const char* value) { + for (int i = 0; i < writers.count(); ++i) { + writers[i]->configOption(name, value); + } + } virtual void timer(const char name[], double ms) { for (int i = 0; i < writers.count(); ++i) { writers[i]->timer(name, ms); diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp index 59e85ed9e6..5cd3e2fbf4 100644 --- a/bench/nanobench.cpp +++ b/bench/nanobench.cpp @@ -21,6 +21,7 @@ #include "SkSurface.h" #if SK_SUPPORT_GPU + #include "gl/GrGLDefines.h" #include "GrContextFactory.h" GrContextFactory gGrFactory; #endif @@ -53,6 +54,8 @@ DEFINE_bool(resetGpuContext, true, "Reset the GrContext before running each benc DEFINE_int32(maxCalibrationAttempts, 3, "Try up to this many times to guess loops for a bench, or skip the bench."); DEFINE_int32(maxLoops, 1000000, "Never run a bench more times than this."); +DEFINE_string(key, "", "Space-separated key/value pairs to add to JSON."); +DEFINE_string(gitHash, "", "Git hash to add to JSON."); static SkString humanize(double ms) { @@ -276,13 +279,25 @@ static void fill_static_options(ResultsWriter* log) { #else log->option("system", "other"); #endif -#if defined(SK_DEBUG) - log->option("build", "DEBUG"); -#else - log->option("build", "RELEASE"); -#endif } +#if SK_SUPPORT_GPU +static void fill_gpu_options(ResultsWriter* log, SkGLContextHelper* ctx) { + const GLubyte* version; + SK_GL_RET(*ctx, version, GetString(GR_GL_VERSION)); + log->configOption("GL_VERSION", (const char*)(version)); + + SK_GL_RET(*ctx, version, GetString(GR_GL_RENDERER)); + log->configOption("GL_RENDERER", (const char*) version); + + SK_GL_RET(*ctx, version, GetString(GR_GL_VENDOR)); + log->configOption("GL_VENDOR", (const char*) version); + + SK_GL_RET(*ctx, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION)); + log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version); +} +#endif + int tool_main(int argc, char** argv); int tool_main(int argc, char** argv) { SetupCrashHandler(); @@ -295,12 +310,21 @@ int tool_main(int argc, char** argv) { } MultiResultsWriter log; - SkAutoTDelete<JSONResultsWriter> json; + SkAutoTDelete<NanoJSONResultsWriter> json; if (!FLAGS_outResultsFile.isEmpty()) { - json.reset(SkNEW(JSONResultsWriter(FLAGS_outResultsFile[0]))); + const char* gitHash = FLAGS_gitHash.isEmpty() ? "unknown-revision" : FLAGS_gitHash[0]; + json.reset(SkNEW(NanoJSONResultsWriter(FLAGS_outResultsFile[0], gitHash))); log.add(json.get()); } CallEnd<MultiResultsWriter> ender(log); + + if (1 == FLAGS_key.count() % 2) { + SkDebugf("ERROR: --key must be passed with an even number of arguments.\n"); + return 1; + } + for (int i = 1; i < FLAGS_key.count(); i += 2) { + log.key(FLAGS_key[i-1], FLAGS_key[i]); + } fill_static_options(&log); const double overhead = estimate_timer_overhead(); @@ -323,12 +347,14 @@ int tool_main(int argc, char** argv) { if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) { continue; } - log.bench(bench->getName(), bench->getSize().fX, bench->getSize().fY); SkTDArray<Target*> targets; create_targets(bench.get(), &targets); - bench->preDraw(); + if (!targets.isEmpty()) { + log.bench(bench->getName(), bench->getSize().fX, bench->getSize().fY); + bench->preDraw(); + } for (int j = 0; j < targets.count(); j++) { SkCanvas* canvas = targets[j]->surface.get() ? targets[j]->surface->getCanvas() : NULL; const char* config = targets[j]->config; @@ -349,6 +375,11 @@ int tool_main(int argc, char** argv) { Stats stats(samples.get(), FLAGS_samples); log.config(config); +#if SK_SUPPORT_GPU + if (Benchmark::kGPU_Backend == targets[j]->backend) { + fill_gpu_options(&log, targets[j]->gl); + } +#endif log.timer("min_ms", stats.min); log.timer("median_ms", stats.median); log.timer("mean_ms", stats.mean); |