aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/ResultsWriter.cpp59
-rw-r--r--bench/ResultsWriter.h236
-rw-r--r--bench/nanobench.cpp62
-rw-r--r--gyp/bench.gyp1
-rw-r--r--gyp/iOSShell.gyp1
-rw-r--r--gyp/tools.gyp1
-rw-r--r--tools/PictureResultsWriter.h38
7 files changed, 83 insertions, 315 deletions
diff --git a/bench/ResultsWriter.cpp b/bench/ResultsWriter.cpp
deleted file mode 100644
index 0ab8cb1908..0000000000
--- a/bench/ResultsWriter.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Helper functions for result writing operations.
- */
-
-#include "ResultsWriter.h"
-#include "SkString.h"
-#include "SkTArray.h"
-
-Json::Value* SkFindNamedNode(Json::Value* root, const char name[]) {
- Json::Value* search_results = NULL;
- for(Json::Value::iterator iter = root->begin();
- iter!= root->end(); ++iter) {
- if(SkString(name).equals((*iter)["name"].asCString())) {
- search_results = &(*iter);
- break;
- }
- }
-
- if(search_results != NULL) {
- return search_results;
- } else {
- Json::Value* new_val = &(root->append(Json::Value()));
- (*new_val)["name"] = name;
- return new_val;
- }
-}
-
-Json::Value SkMakeBuilderJSON(const SkString &builderName) {
- static const int kNumKeys = 6;
- static const char* kKeys[kNumKeys] = {
- "role", "os", "model", "gpu", "arch", "configuration"};
- Json::Value builderData;
-
- if (!builderName.isEmpty()) {
- SkTArray<SkString> splitBuilder;
- SkStrSplit(builderName.c_str(), "-", &splitBuilder);
- SkASSERT(splitBuilder.count() >= kNumKeys);
- for (int i = 0; i < kNumKeys && i < splitBuilder.count(); ++i) {
- builderData[kKeys[i]] = splitBuilder[i].c_str();
- }
- builderData["builderName"] = builderName.c_str();
- if (kNumKeys < splitBuilder.count()) {
- SkString extras;
- for (int i = kNumKeys; i < splitBuilder.count(); ++i) {
- extras.append(splitBuilder[i]);
- if (i != splitBuilder.count() - 1) {
- extras.append("-");
- }
- }
- builderData["badParams"] = extras.c_str();
- }
- }
- return builderData;
-}
diff --git a/bench/ResultsWriter.h b/bench/ResultsWriter.h
index dc45f192f5..56283732ec 100644
--- a/bench/ResultsWriter.h
+++ b/bench/ResultsWriter.h
@@ -20,148 +20,31 @@
/**
* Base class for writing out the bench results.
*
- * TODO(jcgregorio) Add info if tests fail to converge?
+ * Default implementation does nothing.
*/
class ResultsWriter : SkNoncopyable {
public:
- virtual ~ResultsWriter() {};
+ 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;
+ // Record one key value pair that makes up a unique key for this type of run, e.g.
+ // builder name, machine type, Debug/Release, etc.
+ virtual void key(const char name[], const char value[]) {}
- // 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;
+ // Record one key value pair that describes the run instance, e.g. git hash, build number.
+ virtual void property(const char name[], const char value[]) {}
- // Denotes the start of a specific benchmark. Once bench is called,
+ // Denote the start of a specific benchmark. Once bench is called,
// then config and timer can be called multiple times to record runs.
- virtual void bench(const char name[], int32_t x, int32_t y) = 0;
+ virtual void bench(const char name[], int32_t x, int32_t y) {}
- // Records the specific configuration a bench is run under, such as "8888".
- virtual void config(const char name[]) = 0;
+ // Record the specific configuration a bench is run under, such as "8888".
+ virtual void config(const char name[]) {}
- // Records the options for a configuration, such as "GL_RENDERER".
- virtual void configOption(const char name[], const char* value) = 0;
+ // Record the options for a configuration, such as "GL_RENDERER".
+ virtual void configOption(const char name[], const char* value) {}
- // Records a single test metric.
- virtual void timer(const char name[], double ms) = 0;
-
- // Call when all results are finished.
- virtual void end() = 0;
-};
-
-/**
- * This ResultsWriter handles writing out the human readable format of the
- * bench results.
- */
-class LoggerResultsWriter : public ResultsWriter {
-public:
- explicit LoggerResultsWriter(BenchLogger& logger, const char* timeFormat)
- : fLogger(logger)
- , 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));
- }
- virtual void bench(const char name[], int32_t x, int32_t y) {
- fLogger.logProgress(SkStringPrintf(
- "\nrunning bench [%3d %3d] %40s", x, y, name));
- }
- 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));
- }
- virtual void end() {
- fLogger.logProgress("\n");
- }
-private:
- BenchLogger& fLogger;
- const char* fTimeFormat;
-};
-
-/**
- * This ResultsWriter handles writing out the results in JSON.
- *
- * The output looks like (except compressed to a single line):
- *
- * {
- * "options" : {
- * "alpha" : "0xFF",
- * "scale" : "0",
- * ...
- * "system" : "UNIX"
- * },
- * "results" : [
- * {
- * "name" : "Xfermode_Luminosity_640_480",
- * "results" : [
- * {
- * "name": "565",
- * "cmsecs" : 143.188128906250,
- * "msecs" : 143.835957031250
- * },
- * ...
- */
-
-Json::Value* SkFindNamedNode(Json::Value* root, const char name[]);
-Json::Value SkMakeBuilderJSON(const SkString &buildername);
-
-class JSONResultsWriter : public ResultsWriter {
-public:
- explicit JSONResultsWriter(const char filename[])
- : fFilename(filename)
- , fRoot()
- , fResults(fRoot["results"])
- , 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;
- }
- 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(&fResults, sk_name.c_str());
- fBench = &(*bench_node)["results"];
- }
- virtual void config(const char name[]) {
- 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;
+ // Record a single test metric.
+ virtual void timer(const char name[], double ms) {}
};
/**
@@ -175,11 +58,8 @@ private:
"os": "Android",
"model": "GalaxyNexus",
}
- "options": {
- "GL_Version": "3.1",
- ...
- },
"gitHash": "d1830323662ae8ae06908b97f15180fd25808894",
+ "build_number": "1234",
"results" : {
"Xfermode_Luminosity_640_480" : {
"8888" : {
@@ -191,19 +71,26 @@ private:
*/
class NanoJSONResultsWriter : public ResultsWriter {
public:
- explicit NanoJSONResultsWriter(const char filename[], const char gitHash[])
+ explicit NanoJSONResultsWriter(const char filename[])
: fFilename(filename)
, fRoot()
, fResults(fRoot["results"])
, fBench(NULL)
- , fConfig(NULL) {
- fRoot["gitHash"] = gitHash;
+ , fConfig(NULL) {}
+
+ ~NanoJSONResultsWriter() {
+ SkFILEWStream stream(fFilename.c_str());
+ stream.writeText(Json::StyledWriter().write(fRoot).c_str());
+ stream.flush();
}
+
+ // Added under "key".
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;
+ // Inserted directly into the root.
+ virtual void property(const char name[], const char value[]) {
+ fRoot[name] = value;
}
virtual void bench(const char name[], int32_t x, int32_t y) {
SkString id = SkStringPrintf( "%s_%d_%d", name, x, y);
@@ -225,13 +112,8 @@ public:
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:
+private:
SkString fFilename;
Json::Value fRoot;
Json::Value& fResults;
@@ -240,64 +122,4 @@ private:
};
-/**
- * This ResultsWriter writes out to multiple ResultsWriters.
- */
-class MultiResultsWriter : public ResultsWriter {
-public:
- MultiResultsWriter() : writers() {
- };
- 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);
- }
- }
- virtual void bench(const char name[], int32_t x, int32_t y) {
- for (int i = 0; i < writers.count(); ++i) {
- writers[i]->bench(name, x, y);
- }
- }
- virtual void config(const char name[]) {
- for (int i = 0; i < writers.count(); ++i) {
- 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);
- }
- }
- virtual void end() {
- for (int i = 0; i < writers.count(); ++i) {
- writers[i]->end();
- }
- }
-private:
- SkTArray<ResultsWriter *> writers;
-};
-
-/**
- * Calls the end() method of T on destruction.
- */
-template <typename T> class CallEnd : SkNoncopyable {
-public:
- CallEnd(T& obj) : fObj(obj) {}
- ~CallEnd() { fObj.end(); }
-private:
- T& fObj;
-};
-
#endif
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index fedc9ea29f..6968d6dac2 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -64,11 +64,10 @@ DEFINE_string(outResultsFile, "", "If given, write results here as JSON.");
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(properties, "",
+ "Space-separated key/value pairs to add to JSON identifying this nanobench run.");
DEFINE_string(key, "",
"Space-separated key/value pairs to add to JSON identifying this bench config.");
-DEFINE_string(options, "",
- "Space-separated option/value pairs to add to JSON, logging extra info.");
-DEFINE_string(gitHash, "", "Git hash to add to JSON.");
DEFINE_string(clip, "0,0,1000,1000", "Clip for SKPs.");
DEFINE_string(scales, "1.0", "Space-separated scales for SKPs.");
@@ -392,20 +391,6 @@ static void create_targets(SkTDArray<Target*>* targets, Benchmark* b,
}
}
-static void fill_static_options(ResultsWriter* log) {
-#if defined(SK_BUILD_FOR_WIN32)
- log->option("system", "WIN32");
-#elif defined(SK_BUILD_FOR_MAC)
- log->option("system", "MAC");
-#elif defined(SK_BUILD_FOR_ANDROID)
- log->option("system", "ANDROID");
-#elif defined(SK_BUILD_FOR_UNIX)
- log->option("system", "UNIX");
-#else
- log->option("system", "other");
-#endif
-}
-
#if SK_SUPPORT_GPU
static void fill_gpu_options(ResultsWriter* log, SkGLContextHelper* ctx) {
const GrGLubyte* version;
@@ -553,30 +538,25 @@ int nanobench_main() {
}
}
- MultiResultsWriter log;
- SkAutoTDelete<NanoJSONResultsWriter> json;
+ SkAutoTDelete<ResultsWriter> log(SkNEW(ResultsWriter));
if (!FLAGS_outResultsFile.isEmpty()) {
- const char* gitHash = FLAGS_gitHash.isEmpty() ? "unknown-revision" : FLAGS_gitHash[0];
- json.reset(SkNEW(NanoJSONResultsWriter(FLAGS_outResultsFile[0], gitHash)));
- log.add(json.get());
+ log.reset(SkNEW(NanoJSONResultsWriter(FLAGS_outResultsFile[0])));
}
- CallEnd<MultiResultsWriter> ender(log);
- if (1 == FLAGS_key.count() % 2) {
- SkDebugf("ERROR: --key must be passed with an even number of arguments.\n");
+ if (1 == FLAGS_properties.count() % 2) {
+ SkDebugf("ERROR: --properties 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]);
+ for (int i = 1; i < FLAGS_properties.count(); i += 2) {
+ log->property(FLAGS_properties[i-1], FLAGS_properties[i]);
}
- fill_static_options(&log);
- if (1 == FLAGS_options.count() % 2) {
- SkDebugf("ERROR: --options must be passed with an even number of arguments.\n");
+ 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_options.count(); i += 2) {
- log.option(FLAGS_options[i-1], FLAGS_options[i]);
+ for (int i = 1; i < FLAGS_key.count(); i += 2) {
+ log->key(FLAGS_key[i-1], FLAGS_key[i]);
}
const double overhead = estimate_timer_overhead();
@@ -608,7 +588,7 @@ int nanobench_main() {
create_targets(&targets, bench.get(), configs);
if (!targets.isEmpty()) {
- log.bench(bench->getName(), bench->getSize().fX, bench->getSize().fY);
+ log->bench(bench->getName(), bench->getSize().fX, bench->getSize().fY);
bench->preDraw();
}
for (int j = 0; j < targets.count(); j++) {
@@ -644,18 +624,18 @@ int nanobench_main() {
}
Stats stats(samples.get(), FLAGS_samples);
- log.config(config);
- benchStream.fillCurrentOptions(&log);
+ log->config(config);
+ benchStream.fillCurrentOptions(log.get());
#if SK_SUPPORT_GPU
if (Benchmark::kGPU_Backend == targets[j]->config.backend) {
- fill_gpu_options(&log, targets[j]->gl);
+ fill_gpu_options(log.get(), targets[j]->gl);
}
#endif
- log.timer("min_ms", stats.min);
- log.timer("median_ms", stats.median);
- log.timer("mean_ms", stats.mean);
- log.timer("max_ms", stats.max);
- log.timer("stddev_ms", sqrt(stats.var));
+ log->timer("min_ms", stats.min);
+ log->timer("median_ms", stats.median);
+ log->timer("mean_ms", stats.mean);
+ log->timer("max_ms", stats.max);
+ log->timer("stddev_ms", sqrt(stats.var));
if (kAutoTuneLoops != FLAGS_loops) {
if (targets.count() == 1) {
diff --git a/gyp/bench.gyp b/gyp/bench.gyp
index d53e0f7ac6..498816940a 100644
--- a/gyp/bench.gyp
+++ b/gyp/bench.gyp
@@ -12,7 +12,6 @@
'../gm/gm.cpp',
'../bench/GMBench.cpp',
'../bench/SKPBench.cpp',
- '../bench/ResultsWriter.cpp',
'../bench/nanobench.cpp',
],
'includes': [
diff --git a/gyp/iOSShell.gyp b/gyp/iOSShell.gyp
index 45f1effd5d..a0eb00ca69 100644
--- a/gyp/iOSShell.gyp
+++ b/gyp/iOSShell.gyp
@@ -20,7 +20,6 @@
'sources': [
'../bench/GMBench.cpp',
'../bench/SKPBench.cpp',
- '../bench/ResultsWriter.cpp',
'../bench/nanobench.cpp',
'../tests/skia_test.cpp',
'../tools/iOSShell.cpp',
diff --git a/gyp/tools.gyp b/gyp/tools.gyp
index d02aaca99c..66b84db66f 100644
--- a/gyp/tools.gyp
+++ b/gyp/tools.gyp
@@ -387,7 +387,6 @@
'sources': [
'../bench/BenchLogger.cpp',
'../bench/BenchLogger.h',
- '../bench/ResultsWriter.cpp',
'../tools/PictureBenchmark.cpp',
'../tools/PictureResultsWriter.h',
'../tools/bench_pictures_main.cpp',
diff --git a/tools/PictureResultsWriter.h b/tools/PictureResultsWriter.h
index f3b2da8409..9ef1666ee1 100644
--- a/tools/PictureResultsWriter.h
+++ b/tools/PictureResultsWriter.h
@@ -174,7 +174,7 @@ private:
class PictureJSONResultsWriter : public PictureResultsWriter {
public:
- PictureJSONResultsWriter(const char filename[],
+ PictureJSONResultsWriter(const char filename[],
const char builderName[],
int buildNumber,
int timestamp,
@@ -186,7 +186,7 @@ public:
fTimestamp = timestamp;
fGitHash = SkString(gitHash);
fGitNumber = gitNumber;
- fBuilderData = SkMakeBuilderJSON(fBuilderName);
+ fBuilderData = this->makeBuilderJson();
}
virtual void bench(const char name[], int32_t x, int32_t y) SK_OVERRIDE {
@@ -234,7 +234,7 @@ public:
vals++) {
times.push_back((*vals).asDouble());
}
- qsort(static_cast<void*>(times.begin()), times.count(),
+ qsort(static_cast<void*>(times.begin()), times.count(),
sizeof(double), PictureJSONResultsWriter::CompareDoubles);
data["value"] = times[static_cast<int>(times.count() * 0.25f)];
data["params"]["measurementType"] = iter.key().asString();
@@ -245,12 +245,40 @@ public:
fStream.flush();
}
private:
+ Json::Value makeBuilderJson() const {
+ static const int kNumKeys = 6;
+ static const char* kKeys[kNumKeys] = {
+ "role", "os", "model", "gpu", "arch", "configuration"};
+ Json::Value builderData;
+
+ if (!fBuilderName.isEmpty()) {
+ SkTArray<SkString> splitBuilder;
+ SkStrSplit(fBuilderName.c_str(), "-", &splitBuilder);
+ SkASSERT(splitBuilder.count() >= kNumKeys);
+ for (int i = 0; i < kNumKeys && i < splitBuilder.count(); ++i) {
+ builderData[kKeys[i]] = splitBuilder[i].c_str();
+ }
+ builderData["builderName"] = fBuilderName.c_str();
+ if (kNumKeys < splitBuilder.count()) {
+ SkString extras;
+ for (int i = kNumKeys; i < splitBuilder.count(); ++i) {
+ extras.append(splitBuilder[i]);
+ if (i != splitBuilder.count() - 1) {
+ extras.append("-");
+ }
+ }
+ builderData["badParams"] = extras.c_str();
+ }
+ }
+ return builderData;
+ }
+
static int CompareDoubles(const void* p1, const void* p2) {
if(*static_cast<const double*>(p1) < *static_cast<const double*>(p2)) {
return -1;
- } else if(*static_cast<const double*>(p1) ==
+ } else if(*static_cast<const double*>(p1) ==
*static_cast<const double*>(p2)) {
- return 0;
+ return 0;
} else {
return 1;
}