From 92007583e43115998412ac8b0a06cc2780eb025c Mon Sep 17 00:00:00 2001 From: mtklein Date: Fri, 1 Aug 2014 07:46:52 -0700 Subject: SKPs-as-benches in nanobench This is meant to replace bench_pictures. CQ_EXTRA_TRYBOTS=tryserver.skia:Build-Mac10.7-Clang-Arm7-Release-iOS-Trybot BUG=skia: R=bsalomon@google.com, jcgregorio@google.com, mtklein@google.com Author: mtklein@chromium.org Review URL: https://codereview.chromium.org/425393004 --- bench/GMBench.cpp | 1 + bench/GMBench.h | 4 ++ bench/SKPBench.cpp | 37 +++++++++++++++++ bench/SKPBench.h | 37 +++++++++++++++++ bench/nanobench.cpp | 112 ++++++++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 183 insertions(+), 8 deletions(-) create mode 100644 bench/SKPBench.cpp create mode 100644 bench/SKPBench.h (limited to 'bench') diff --git a/bench/GMBench.cpp b/bench/GMBench.cpp index dbd1d7b24a..bdf32904e8 100644 --- a/bench/GMBench.cpp +++ b/bench/GMBench.cpp @@ -49,3 +49,4 @@ SkIPoint GMBench::onGetSize() { SkISize size = fGM->getISize(); return SkIPoint::Make(size.fWidth, size.fHeight); } + diff --git a/bench/GMBench.h b/bench/GMBench.h index 75cee6c063..e224052827 100644 --- a/bench/GMBench.h +++ b/bench/GMBench.h @@ -4,6 +4,8 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#ifndef GMBench_DEFINED +#define GMBench_DEFINED #include "Benchmark.h" #include "SkCanvas.h" @@ -29,3 +31,5 @@ private: SkString fName; typedef Benchmark INHERITED; }; + +#endif diff --git a/bench/SKPBench.cpp b/bench/SKPBench.cpp new file mode 100644 index 0000000000..cd7d4b00e1 --- /dev/null +++ b/bench/SKPBench.cpp @@ -0,0 +1,37 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SKPBench.h" + +SKPBench::SKPBench(const char* name, const SkPicture* pic, const SkIRect& clip, SkScalar scale) + : fPic(SkRef(pic)) + , fClip(clip) + , fScale(scale) { + fName.printf("%s_%.2g", name, scale); +} + +const char* SKPBench::onGetName() { + return fName.c_str(); +} + +bool SKPBench::isSuitableFor(Backend backend) { + return backend != kNonRendering_Backend; +} + +SkIPoint SKPBench::onGetSize() { + return SkIPoint::Make(fClip.width(), fClip.height()); +} + +void SKPBench::onDraw(const int loops, SkCanvas* canvas) { + canvas->save(); + canvas->scale(fScale, fScale); + for (int i = 0; i < loops; i++) { + fPic->draw(canvas); + canvas->flush(); + } + canvas->restore(); +} diff --git a/bench/SKPBench.h b/bench/SKPBench.h new file mode 100644 index 0000000000..9cc9192820 --- /dev/null +++ b/bench/SKPBench.h @@ -0,0 +1,37 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SKPBench_DEFINED +#define SKPBench_DEFINED + +#include "Benchmark.h" +#include "SkCanvas.h" +#include "SkPicture.h" + +/** + * Runs an SkPicture as a benchmark by repeatedly drawing it scaled inside a device clip. + */ +class SKPBench : public Benchmark { +public: + SKPBench(const char* name, const SkPicture*, const SkIRect& devClip, SkScalar scale); + +protected: + virtual const char* onGetName() SK_OVERRIDE; + virtual bool isSuitableFor(Backend backend) SK_OVERRIDE; + virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE; + virtual SkIPoint onGetSize() SK_OVERRIDE; + +private: + SkAutoTUnref fPic; + const SkIRect fClip; + const SkScalar fScale; + SkString fName; + + typedef Benchmark INHERITED; +}; + +#endif diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp index 742a6ed11d..f6fd90e74a 100644 --- a/bench/nanobench.cpp +++ b/bench/nanobench.cpp @@ -11,9 +11,11 @@ #include "CrashHandler.h" #include "GMBench.h" #include "ResultsWriter.h" +#include "SKPBench.h" #include "Stats.h" #include "Timer.h" +#include "SkOSFile.h" #include "SkCanvas.h" #include "SkCommonFlags.h" #include "SkForceLinking.h" @@ -49,6 +51,9 @@ 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."); +DEFINE_string(clip, "0,0,1000,1000", "Clip for SKPs."); +DEFINE_string(scales, "1.0", "Space-separated scales for SKPs."); + static SkString humanize(double ms) { if (ms > 1e+3) return SkStringPrintf("%.3gs", ms/1e3); if (ms < 1e-3) return SkStringPrintf("%.3gns", ms*1e6); @@ -357,28 +362,108 @@ static void fill_gpu_options(ResultsWriter* log, SkGLContextHelper* ctx) { class BenchmarkStream { public: - BenchmarkStream() : fBenches(BenchRegistry::Head()) , fGMs(skiagm::GMRegistry::Head()) {} + BenchmarkStream() : fBenches(BenchRegistry::Head()) + , fGMs(skiagm::GMRegistry::Head()) + , fCurrentScale(0) + , fCurrentSKP(0) { + for (int i = 0; i < FLAGS_skps.count(); i++) { + if (SkStrEndsWith(FLAGS_skps[i], ".skp")) { + fSKPs.push_back() = FLAGS_skps[i]; + } else { + SkOSFile::Iter it(FLAGS_skps[i], ".skp"); + SkString path; + while (it.next(&path)) { + fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str()); + } + } + } - Benchmark* next(const char** sourceType) { + if (4 != sscanf(FLAGS_clip[0], "%d,%d,%d,%d", + &fClip.fLeft, &fClip.fTop, &fClip.fRight, &fClip.fBottom)) { + SkDebugf("Can't parse %s from --clip as an SkIRect.\n", FLAGS_clip[0]); + exit(1); + } + + for (int i = 0; i < FLAGS_scales.count(); i++) { + if (1 != sscanf(FLAGS_scales[i], "%f", &fScales.push_back())) { + SkDebugf("Can't parse %s from --scales as an SkScalar.\n", FLAGS_scales[i]); + exit(1); + } + } + } + + Benchmark* next() { if (fBenches) { Benchmark* bench = fBenches->factory()(NULL); fBenches = fBenches->next(); - *sourceType = "bench"; + fSourceType = "bench"; return bench; } + while (fGMs) { SkAutoTDelete gm(fGMs->factory()(NULL)); fGMs = fGMs->next(); if (gm->getFlags() & skiagm::GM::kAsBench_Flag) { - *sourceType = "gm"; + fSourceType = "gm"; return SkNEW_ARGS(GMBench, (gm.detach())); } } + + while (fCurrentScale < fScales.count()) { + while (fCurrentSKP < fSKPs.count()) { + const SkString& path = fSKPs[fCurrentSKP++]; + + // Not strictly necessary, as it will be checked again later, + // but helps to avoid a lot of pointless work if we're going to skip it. + if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path.c_str())) { + continue; + } + + SkAutoTUnref stream(SkStream::NewFromFile(path.c_str())); + if (stream.get() == NULL) { + SkDebugf("Could not read %s.\n", path.c_str()); + exit(1); + } + + SkAutoTUnref pic(SkPicture::CreateFromStream(stream.get())); + if (pic.get() == NULL) { + SkDebugf("Could not read %s as an SkPicture.\n", path.c_str()); + exit(1); + } + + SkString name = SkOSPath::Basename(path.c_str()); + + fSourceType = "skp"; + return SkNEW_ARGS(SKPBench, + (name.c_str(), pic.get(), fClip, fScales[fCurrentScale])); + } + fCurrentSKP = 0; + fCurrentScale++; + } + return NULL; } + + void fillCurrentOptions(ResultsWriter* log) const { + log->configOption("source_type", fSourceType); + if (0 == strcmp(fSourceType, "skp")) { + log->configOption("clip", + SkStringPrintf("%d %d %d %d", fClip.fLeft, fClip.fTop, + fClip.fRight, fClip.fBottom).c_str()); + log->configOption("scale", SkStringPrintf("%.2g", fScales[fCurrentScale]).c_str()); + } + } + private: const BenchRegistry* fBenches; const skiagm::GMRegistry* fGMs; + SkIRect fClip; + SkTArray fScales; + SkTArray fSKPs; + + const char* fSourceType; + int fCurrentScale; + int fCurrentSKP; }; int nanobench_main(); @@ -427,9 +512,8 @@ int nanobench_main() { SkTDArray configs; create_configs(&configs); - BenchmarkStream benches; - const char* sourceType; - while (Benchmark* b = benches.next(&sourceType)) { + BenchmarkStream benchStream; + while (Benchmark* b = benchStream.next()) { SkAutoTDelete bench(b); if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) { continue; @@ -446,6 +530,18 @@ int nanobench_main() { SkCanvas* canvas = targets[j]->surface.get() ? targets[j]->surface->getCanvas() : NULL; const char* config = targets[j]->config.name; +#if SK_DEBUG + // skia:2797 Some SKPs SkASSERT in debug mode. Skip them for now. + if (0 == strcmp("565", config) + && ( SkStrStartsWith(bench->getName(), "desk_carsvg.skp") + || SkStrStartsWith(bench->getName(), "desk_forecastio.skp") + || SkStrStartsWith(bench->getName(), "tabl_cnet.skp") + || SkStrStartsWith(bench->getName(), "tabl_googlecalendar.skp"))) { + SkDebugf("Skipping 565 %s. It'd assert.\n", bench->getName()); + continue; + } +#endif + const int loops = #if SK_SUPPORT_GPU Benchmark::kGPU_Backend == targets[j]->config.backend @@ -462,7 +558,7 @@ int nanobench_main() { Stats stats(samples.get(), FLAGS_samples); log.config(config); - log.configOption("source_type", sourceType); + benchStream.fillCurrentOptions(&log); #if SK_SUPPORT_GPU if (Benchmark::kGPU_Backend == targets[j]->config.backend) { fill_gpu_options(&log, targets[j]->gl); -- cgit v1.2.3