diff options
author | bsalomon <bsalomon@google.com> | 2014-08-07 14:28:50 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-08-07 14:28:50 -0700 |
commit | 6eb03cc06d0bc60da5277a83aa0251a475794b04 (patch) | |
tree | f359945cb7d54f915bb91f28f44949fffd42e864 /bench | |
parent | 72ebb9f1dc1ed4d64127b02fed93446b278069d1 (diff) |
Add option to dump images from nanobench.
Add option to set the repeat count to any number, replacs the --runOnce flag.
R=mtklein@google.com
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/450743002
Diffstat (limited to 'bench')
-rw-r--r-- | bench/nanobench.cpp | 109 |
1 files changed, 90 insertions, 19 deletions
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp index c808183b19..245aa0ed1d 100644 --- a/bench/nanobench.cpp +++ b/bench/nanobench.cpp @@ -31,12 +31,27 @@ __SK_FORCE_IMAGE_DECODER_LINKING; -#if SK_DEBUG - DEFINE_bool(runOnce, true, "Run each benchmark just once?"); +static const int kAutoTuneLoops = -1; + +static const int kDefaultLoops = +#ifdef SK_DEBUG + 1; #else - DEFINE_bool(runOnce, false, "Run each benchmark just once?"); + kAutoTuneLoops; #endif +static SkString loops_help_txt() { + SkString help; + help.printf("Number of times to run each bench. Set this to %d to auto-" + "tune for each bench. Timings are only reported when auto-tuning.", + kAutoTuneLoops); + return help; +} + +DEFINE_int32(loops, kDefaultLoops, loops_help_txt().c_str()); + +DEFINE_string2(writePath, w, "", "If set, write benches here as .pngs."); + DEFINE_int32(samples, 10, "Number of samples to measure for each bench."); DEFINE_int32(overheadLoops, 100000, "Loops to estimate timer overhead."); DEFINE_double(overheadGoal, 0.0001, @@ -67,6 +82,9 @@ static SkString humanize(double ms) { #define HUMANIZE(ms) humanize(ms).c_str() static double time(int loops, Benchmark* bench, SkCanvas* canvas, SkGLContextHelper* gl) { + if (canvas) { + canvas->clear(SK_ColorWHITE); + } WallTimer timer; timer.start(); if (bench) { @@ -105,17 +123,50 @@ static int clamp_loops(int loops) { return loops; } +static bool write_canvas_png(SkCanvas* canvas, const SkString& filename) { + if (filename.isEmpty()) { + return false; + } + if (kUnknown_SkColorType == canvas->imageInfo().fColorType) { + return false; + } + SkBitmap bmp; + bmp.setInfo(canvas->imageInfo()); + if (!canvas->readPixels(&bmp, 0, 0)) { + SkDebugf("Can't read canvas pixels.\n"); + return false; + } + SkString dir = SkOSPath::Dirname(filename.c_str()); + if (!sk_mkdir(dir.c_str())) { + SkDebugf("Can't make dir %s.\n", dir.c_str()); + return false; + } + SkFILEWStream stream(filename.c_str()); + if (!stream.isValid()) { + SkDebugf("Can't write %s.\n", filename.c_str()); + return false; + } + if (!SkImageEncoder::EncodeStream(&stream, bmp, SkImageEncoder::kPNG_Type, 100)) { + SkDebugf("Can't encode a PNG.\n"); + return false; + } + return true; +} + +static int kFailedLoops = -2; static int cpu_bench(const double overhead, Benchmark* bench, SkCanvas* canvas, double* samples) { // First figure out approximately how many loops of bench it takes to make overhead negligible. double bench_plus_overhead = 0.0; int round = 0; - while (bench_plus_overhead < overhead) { - if (round++ == FLAGS_maxCalibrationAttempts) { - SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skipping.\n", - bench->getName(), HUMANIZE(bench_plus_overhead), HUMANIZE(overhead)); - return 0; + if (kAutoTuneLoops == FLAGS_loops) { + while (bench_plus_overhead < overhead) { + if (round++ == FLAGS_maxCalibrationAttempts) { + SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skipping.\n", + bench->getName(), HUMANIZE(bench_plus_overhead), HUMANIZE(overhead)); + return kFailedLoops; + } + bench_plus_overhead = time(1, bench, canvas, NULL); } - bench_plus_overhead = time(1, bench, canvas, NULL); } // Later we'll just start and stop the timer once but loop N times. @@ -134,9 +185,13 @@ static int cpu_bench(const double overhead, Benchmark* bench, SkCanvas* canvas, // bench_plus_overhead - overhead) // // Luckily, this also works well in practice. :) - const double numer = overhead / FLAGS_overheadGoal - overhead; - const double denom = bench_plus_overhead - overhead; - const int loops = clamp_loops(FLAGS_runOnce ? 1 : (int)ceil(numer / denom)); + int loops = FLAGS_loops; + if (kAutoTuneLoops == loops) { + const double numer = overhead / FLAGS_overheadGoal - overhead; + const double denom = bench_plus_overhead - overhead; + loops = (int)ceil(numer / denom); + } + loops = clamp_loops(loops); for (int i = 0; i < FLAGS_samples; i++) { samples[i] = time(loops, bench, canvas, NULL) / loops; @@ -154,8 +209,9 @@ static int gpu_bench(SkGLContextHelper* gl, SK_GL(*gl, Finish()); // First, figure out how many loops it'll take to get a frame up to FLAGS_gpuMs. - int loops = 1; - if (!FLAGS_runOnce) { + int loops = FLAGS_loops; + if (kAutoTuneLoops == loops) { + loops = 1; double elapsed = 0; do { loops *= 2; @@ -474,11 +530,19 @@ int nanobench_main() { SetupCrashHandler(); SkAutoGraphics ag; - if (FLAGS_runOnce) { + if (kAutoTuneLoops != FLAGS_loops) { FLAGS_samples = 1; FLAGS_gpuFrameLag = 0; } + if (!FLAGS_writePath.isEmpty()) { + SkDebugf("Writing files to %s.\n", FLAGS_writePath[0]); + if (!sk_mkdir(FLAGS_writePath[0])) { + SkDebugf("Could not create %s. Files won't be written.\n", FLAGS_writePath[0]); + FLAGS_writePath.set(0, NULL); + } + } + MultiResultsWriter log; SkAutoTDelete<NanoJSONResultsWriter> json; if (!FLAGS_outResultsFile.isEmpty()) { @@ -502,8 +566,8 @@ int nanobench_main() { SkAutoTMalloc<double> samples(FLAGS_samples); - if (FLAGS_runOnce) { - SkDebugf("--runOnce is true; times would only be misleading so we won't print them.\n"); + if (kAutoTuneLoops != FLAGS_loops) { + SkDebugf("Fixed number of loops; times would only be misleading so we won't print them.\n"); } else if (FLAGS_verbose) { // No header. } else if (FLAGS_quiet) { @@ -549,7 +613,14 @@ int nanobench_main() { #endif cpu_bench( overhead, bench.get(), canvas, samples.get()); - if (loops == 0) { + if (canvas && !FLAGS_writePath.isEmpty() && NULL != FLAGS_writePath[0]) { + SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config); + pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getName()); + pngFilename.append(".png"); + write_canvas_png(canvas, pngFilename); + } + + if (kFailedLoops == loops) { // Can't be timed. A warning note has already been printed. continue; } @@ -568,7 +639,7 @@ int nanobench_main() { log.timer("max_ms", stats.max); log.timer("stddev_ms", sqrt(stats.var)); - if (FLAGS_runOnce) { + if (kAutoTuneLoops != FLAGS_loops) { if (targets.count() == 1) { config = ""; // Only print the config if we run the same bench on more than one. } |