skia2/bench/DeferredCanvasBench.cpp
mtklein@google.com dbd41c8857 It looks like we're not always running long enough to give the GPU counters time to converge (and possibly the same for CPU too, but GPU is definitely worse off).
This CL changes our convergence logic from
  - did the last run take more than x milliseconds?
to
  - did the last run take more x milliseconds and are the last two runs within y% of each other?

There's also now an upper limit where we bail out with an error if we haven't yet met the convergence criteria.  Keeping the lower bound is important for benches where the constant overhead is much larger than the work done in the loop; without it we'll see T(1 loop) == T(2 loops) and converge way too early.

This CL also exposed that DeferredCanvasBench had a bug: it was running N^2 loops when we told it to run N.  (My fault.)

I threw in a couple other linty changes that I'd be happy to split off.

BUG=
R=robertphillips@google.com

Review URL: https://codereview.chromium.org/23536046

git-svn-id: http://skia.googlecode.com/svn/trunk@11267 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-09-13 20:11:09 +00:00

105 lines
3.1 KiB
C++

/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBenchmark.h"
#include "SkDeferredCanvas.h"
#include "SkDevice.h"
#include "SkString.h"
class DeferredCanvasBench : public SkBenchmark {
public:
DeferredCanvasBench(const char name[]) {
fName.printf("deferred_canvas_%s", name);
}
enum {
CANVAS_WIDTH = 200,
CANVAS_HEIGHT = 200,
};
protected:
virtual const char* onGetName() {
return fName.c_str();
}
virtual void onDraw(SkCanvas* canvas) {
SkBaseDevice *device = canvas->getDevice()->createCompatibleDevice(
SkBitmap::kARGB_8888_Config, CANVAS_WIDTH, CANVAS_HEIGHT, false);
SkAutoTUnref<SkDeferredCanvas> deferredCanvas(SkDeferredCanvas::Create(device));
device->unref();
initDeferredCanvas(deferredCanvas);
drawInDeferredCanvas(deferredCanvas);
finalizeDeferredCanvas(deferredCanvas);
deferredCanvas->flush();
}
virtual void initDeferredCanvas(SkDeferredCanvas* canvas) = 0;
virtual void drawInDeferredCanvas(SkDeferredCanvas* canvas) = 0;
virtual void finalizeDeferredCanvas(SkDeferredCanvas* canvas) = 0;
SkString fName;
private:
typedef SkBenchmark INHERITED;
};
class SimpleNotificationClient : public SkDeferredCanvas::NotificationClient {
public:
SimpleNotificationClient() : fDummy(false) {}
//bogus virtual implementations that just do something small
virtual void prepareForDraw() SK_OVERRIDE {fDummy = true;}
virtual void storageAllocatedForRecordingChanged(size_t) SK_OVERRIDE {fDummy = false;}
virtual void flushedDrawCommands() SK_OVERRIDE {fDummy = !fDummy;}
private:
bool fDummy;
typedef SkDeferredCanvas::NotificationClient INHERITED;
};
// Test that records very simple draw operations.
// This benchmark aims to capture performance fluctuations in the recording
// overhead of SkDeferredCanvas
class DeferredRecordBench : public DeferredCanvasBench {
public:
DeferredRecordBench()
: INHERITED("record") {
}
protected:
virtual void initDeferredCanvas(SkDeferredCanvas* canvas) SK_OVERRIDE {
canvas->setNotificationClient(&fNotificationClient);
}
virtual void drawInDeferredCanvas(SkDeferredCanvas* canvas) SK_OVERRIDE {
SkRect rect;
rect.setXYWH(0, 0, 10, 10);
SkPaint paint;
for (int i = 0; i < this->getLoops(); i++) {
canvas->save(SkCanvas::kMatrixClip_SaveFlag);
canvas->translate(SkIntToScalar(i * 27 % CANVAS_WIDTH), SkIntToScalar(i * 13 % CANVAS_HEIGHT));
canvas->drawRect(rect, paint);
canvas->restore();
}
}
virtual void finalizeDeferredCanvas(SkDeferredCanvas* canvas) SK_OVERRIDE {
canvas->clear(0x0);
canvas->setNotificationClient(NULL);
}
private:
typedef DeferredCanvasBench INHERITED;
SimpleNotificationClient fNotificationClient;
};
///////////////////////////////////////////////////////////////////////////////
DEF_BENCH( return new DeferredRecordBench(); )