aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/skpbench
diff options
context:
space:
mode:
authorGravatar csmartdalton <csmartdalton@google.com>2016-10-11 18:28:54 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-10-11 18:28:54 -0700
commit5772eaa91d6a10d74959d7732513c5ab9c057e03 (patch)
treefe372c5cbf1da303e91b46f1dfb92751732cffbd /tools/skpbench
parent768bdfca71391016c92239831d66427d0f3b151d (diff)
skpbench: add warmup run
Does actual work while waiting for hardware settings to kick in, rather than just sleeping. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2410373002 Review-Url: https://codereview.chromium.org/2410373002
Diffstat (limited to 'tools/skpbench')
-rw-r--r--tools/skpbench/_hardware.py2
-rw-r--r--tools/skpbench/_hardware_android.py2
-rw-r--r--tools/skpbench/skpbench.cpp70
-rwxr-xr-xtools/skpbench/skpbench.py42
4 files changed, 84 insertions, 32 deletions
diff --git a/tools/skpbench/_hardware.py b/tools/skpbench/_hardware.py
index 9c929c43db..525c4c1e49 100644
--- a/tools/skpbench/_hardware.py
+++ b/tools/skpbench/_hardware.py
@@ -21,7 +21,7 @@ class Hardware:
"""
def __init__(self):
- self.kick_in_time = 0
+ self.warmup_time = 0
def __enter__(self):
return self
diff --git a/tools/skpbench/_hardware_android.py b/tools/skpbench/_hardware_android.py
index d7990dcd81..abeab71d76 100644
--- a/tools/skpbench/_hardware_android.py
+++ b/tools/skpbench/_hardware_android.py
@@ -11,7 +11,7 @@ import time
class HardwareAndroid(Hardware):
def __init__(self, adb):
Hardware.__init__(self)
- self.kick_in_time = 5
+ self.warmup_time = 5
self._adb = adb
self._is_root = self._adb.attempt_root()
if self._is_root:
diff --git a/tools/skpbench/skpbench.cpp b/tools/skpbench/skpbench.cpp
index 6d0381a28d..f452d9d025 100644
--- a/tools/skpbench/skpbench.cpp
+++ b/tools/skpbench/skpbench.cpp
@@ -9,11 +9,14 @@
#include "GrContextFactory.h"
#include "SkCanvas.h"
#include "SkOSFile.h"
+#include "SkPerlinNoiseShader.h"
#include "SkPicture.h"
+#include "SkPictureRecorder.h"
#include "SkStream.h"
#include "SkSurface.h"
#include "SkSurfaceProps.h"
#include "picture_utils.h"
+#include "sk_tool_utils.h"
#include "flags/SkCommandLineFlags.h"
#include "flags/SkCommonFlagsConfig.h"
#include <stdlib.h>
@@ -38,7 +41,7 @@ DEFINE_int32(duration, 5000, "number of milliseconds to run the benchmark");
DEFINE_int32(sampleMs, 50, "minimum duration of a sample");
DEFINE_bool(gpuClock, false, "time on the gpu clock (gpu work only)");
DEFINE_bool(fps, false, "use fps instead of ms");
-DEFINE_string(skp, "", "path to a single .skp file to benchmark");
+DEFINE_string(skp, "", "path to a single .skp file, or 'warmup' for a builtin warmup run");
DEFINE_string(png, "", "if set, save a .png proof to disk at this file location");
DEFINE_int32(verbosity, 4, "level of verbosity (0=none to 5=debug)");
DEFINE_bool(suppressHeader, false, "don't print a header row before the results");
@@ -86,6 +89,7 @@ enum class ExitErr {
};
static void draw_skp_and_flush(SkCanvas*, const SkPicture*);
+static sk_sp<SkPicture> create_warmup_skp();
static bool mkdir_p(const SkString& name);
static SkString join(const SkCommandLineFlags::StringArray&);
static void exitf(ExitErr, const char* format, ...);
@@ -230,31 +234,38 @@ int main(int argc, char** argv) {
SkCommandLineConfigArray configs;
ParseConfigs(FLAGS_config, &configs);
if (configs.count() != 1 || !(config = configs[0]->asConfigGpu())) {
- exitf(ExitErr::kUsage, "invalid config %s, must specify one (and only one) GPU config",
+ exitf(ExitErr::kUsage, "invalid config '%s': must specify one (and only one) GPU config",
join(FLAGS_config).c_str());
}
// Parse the skp.
if (FLAGS_skp.count() != 1) {
- exitf(ExitErr::kUsage, "invalid skp %s, must specify (and only one) skp path name.",
+ exitf(ExitErr::kUsage, "invalid skp '%s': must specify a single skp file, or 'warmup'",
join(FLAGS_skp).c_str());
}
- const char* skpfile = FLAGS_skp[0];
- std::unique_ptr<SkStream> skpstream(SkStream::MakeFromFile(skpfile));
- if (!skpstream) {
- exitf(ExitErr::kIO, "failed to open skp file %s", skpfile);
- }
- sk_sp<SkPicture> skp = SkPicture::MakeFromStream(skpstream.get());
- if (!skp) {
- exitf(ExitErr::kData, "failed to parse skp file %s", skpfile);
+ sk_sp<SkPicture> skp;
+ SkString skpname;
+ if (0 == strcmp(FLAGS_skp[0], "warmup")) {
+ skp = create_warmup_skp();
+ skpname = "warmup";
+ } else {
+ const char* skpfile = FLAGS_skp[0];
+ std::unique_ptr<SkStream> skpstream(SkStream::MakeFromFile(skpfile));
+ if (!skpstream) {
+ exitf(ExitErr::kIO, "failed to open skp file %s", skpfile);
+ }
+ skp = SkPicture::MakeFromStream(skpstream.get());
+ if (!skp) {
+ exitf(ExitErr::kData, "failed to parse skp file %s", skpfile);
+ }
+ skpname = SkOSPath::Basename(skpfile);
}
int width = SkTMin(SkScalarCeilToInt(skp->cullRect().width()), 2048),
height = SkTMin(SkScalarCeilToInt(skp->cullRect().height()), 2048);
if (FLAGS_verbosity >= 3 &&
(width != skp->cullRect().width() || height != skp->cullRect().height())) {
fprintf(stderr, "%s is too large (%ix%i), cropping to %ix%i.\n",
- SkOSPath::Basename(skpfile).c_str(),
- SkScalarCeilToInt(skp->cullRect().width()),
+ skpname.c_str(), SkScalarCeilToInt(skp->cullRect().width()),
SkScalarCeilToInt(skp->cullRect().height()), width, height);
}
@@ -295,6 +306,7 @@ int main(int argc, char** argv) {
width, height, config->getTag().c_str());
}
+ // Run the benchmark.
std::vector<Sample> samples;
if (FLAGS_sampleMs > 0) {
// +1 because we might take one more sample in order to have an odd number.
@@ -302,8 +314,6 @@ int main(int argc, char** argv) {
} else {
samples.reserve(2 * FLAGS_duration);
}
-
- // Run the benchmark.
SkCanvas* canvas = surface->getCanvas();
canvas->translate(-skp->cullRect().x(), -skp->cullRect().y());
if (!FLAGS_gpuClock) {
@@ -315,7 +325,7 @@ int main(int argc, char** argv) {
run_gpu_time_benchmark(testCtx->gpuTimer(), testCtx->fenceSync(), canvas, skp.get(),
&samples);
}
- print_result(samples, config->getTag().c_str(), SkOSPath::Basename(skpfile).c_str());
+ print_result(samples, config->getTag().c_str(), skpname.c_str());
// Save a proof (if one was requested).
if (!FLAGS_png.isEmpty()) {
@@ -342,6 +352,30 @@ static void draw_skp_and_flush(SkCanvas* canvas, const SkPicture* skp) {
canvas->flush();
}
+static sk_sp<SkPicture> create_warmup_skp() {
+ static constexpr SkRect bounds{0, 0, 500, 500};
+ SkPictureRecorder recorder;
+ SkCanvas* recording = recorder.beginRecording(bounds);
+
+ recording->clear(SK_ColorWHITE);
+
+ SkPaint stroke;
+ stroke.setStyle(SkPaint::kStroke_Style);
+ stroke.setStrokeWidth(2);
+
+ // Use a big path to (theoretically) warmup the CPU.
+ SkPath bigPath;
+ sk_tool_utils::make_big_path(bigPath);
+ recording->drawPath(bigPath, stroke);
+
+ // Use a perlin shader to warmup the GPU.
+ SkPaint perlin;
+ perlin.setShader(SkPerlinNoiseShader::MakeTurbulence(0.1f, 0.1f, 1, 0, nullptr));
+ recording->drawRect(bounds, perlin);
+
+ return recorder.finishRecordingAsPicture();
+}
+
bool mkdir_p(const SkString& dirname) {
if (dirname.isEmpty()) {
return true;
@@ -351,8 +385,8 @@ bool mkdir_p(const SkString& dirname) {
static SkString join(const SkCommandLineFlags::StringArray& stringArray) {
SkString joined;
- for (int i = 0; i < FLAGS_config.count(); ++i) {
- joined.appendf(i ? " %s" : "%s", FLAGS_config[i]);
+ for (int i = 0; i < stringArray.count(); ++i) {
+ joined.appendf(i ? " %s" : "%s", stringArray[i]);
}
return joined;
}
diff --git a/tools/skpbench/skpbench.py b/tools/skpbench/skpbench.py
index 932d8d0461..9598162693 100755
--- a/tools/skpbench/skpbench.py
+++ b/tools/skpbench/skpbench.py
@@ -67,6 +67,11 @@ if FLAGS.adb:
else:
import _os_path as _path
+def dump_commandline_if_verbose(commandline):
+ if FLAGS.verbosity >= 4:
+ quoted = ['\'%s\'' % re.sub(r'([\\\'])', r'\\\1', x) for x in commandline]
+ print(' '.join(quoted), file=sys.stderr)
+
class StddevException(Exception):
pass
@@ -111,7 +116,26 @@ class SKPBench:
@classmethod
def print_header(cls):
- subprocess.call(cls.ARGV + ['--duration', '0'])
+ commandline = cls.ARGV + ['--duration', '0']
+ dump_commandline_if_verbose(commandline)
+ subprocess.call(commandline)
+
+ @classmethod
+ def run_warmup(cls, warmup_time):
+ if not warmup_time:
+ return
+ print('running %i second warmup...' % warmup_time)
+ commandline = cls.ARGV + ['--duration', str(warmup_time * 1000),
+ '--config', 'gpu',
+ '--skp', 'warmup']
+ dump_commandline_if_verbose(commandline)
+ output = subprocess.check_output(commandline).decode('utf-8')
+ # validate the warmup run output.
+ for line in output.split('\n'):
+ match = BenchResult.match(line.rstrip())
+ if match and match.bench == 'warmup':
+ return
+ raise Exception('Invalid warmup output:\n%s' % output)
def __init__(self, skp, config, max_stddev, best_result=None):
self.skp = skp
@@ -143,9 +167,7 @@ class SKPBench:
pngfile = _path.join(FLAGS.write_path, self.config,
_path.basename(self.skp) + '.png')
commandline.extend(['--png', pngfile])
- if (FLAGS.verbosity >= 4):
- quoted = ['\'%s\'' % re.sub(r'([\\\'])', r'\\\1', x) for x in commandline]
- print(' '.join(quoted), file=sys.stderr)
+ dump_commandline_if_verbose(commandline)
self._proc = subprocess.Popen(commandline, stdout=subprocess.PIPE)
self._monitor = SubprocessMonitor(self._queue, self._proc)
self._monitor.start()
@@ -233,13 +255,12 @@ def run_benchmarks(configs, skps, hardware):
if FLAGS.verbosity >= 5:
hardware.print_debug_diagnostics()
skpbench.terminate()
- naptime = max(hardware.kick_in_time, exception.sleeptime)
if FLAGS.verbosity >= 1:
print("%s; taking a %i second nap..." %
- (exception.message, naptime), file=sys.stderr)
+ (exception.message, exception.sleeptime), file=sys.stderr)
benches.appendleft(benchargs) # retry the same bench next time.
- hardware.sleep(naptime - hardware.kick_in_time)
- time.sleep(hardware.kick_in_time)
+ hardware.sleep(exception.sleeptime)
+ SKPBench.run_warmup(hardware.warmup_time)
def main():
@@ -263,10 +284,7 @@ def main():
hardware = Hardware()
with hardware:
- if hardware.kick_in_time:
- print("sleeping %i seconds to allow hardware settings to kick in..." %
- hardware.kick_in_time, file=sys.stderr)
- time.sleep(hardware.kick_in_time)
+ SKPBench.run_warmup(hardware.warmup_time)
run_benchmarks(configs, skps, hardware)