Skip to content

Commit

Permalink
oop: Add PaintOpBuffer serialization perf test
Browse files Browse the repository at this point in the history
This uses the serializer that GLES2 serialization uses, which includes
both SkCanvas playback and an additional save/restore op pushed (which
is why this uses 100 ops to try to mitigate that extra simple op but
still use the general path.

From these numbers, I think there's a lot of work to be done.  In
particular, the worst case 81720 ops/s means that 100 ops takes > 1 ms.

*RESULT simple:   serialize= 5996382 ops/s
*RESULT simple: deserialize= 1592268.25 ops/s
*RESULT draw:   serialize= 453231.875 ops/s
*RESULT draw: deserialize= 824889 ops/s
*RESULT flags:   serialize= 119959.28125 ops/s
*RESULT flags: deserialize= 81720.609375 ops/s
*RESULT text:   serialize= 231328.953125 ops/s
*RESULT text: deserialize= 204539.234375 ops/s

Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.android:android_optional_gpu_tests_rel
Change-Id: Ie648476779d2c93598dd1340d036e6287be23a66
Reviewed-on: https://chromium-review.googlesource.com/794992
Commit-Queue: enne <enne@chromium.org>
Reviewed-by: Khushal <khushalsagar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#520264}
  • Loading branch information
quisquous authored and Commit Bot committed Nov 29, 2017
1 parent 4856718 commit eeb00f7
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 0 deletions.
1 change: 1 addition & 0 deletions cc/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,7 @@ cc_test("cc_perftests") {
"ipc/cc_serialization_perftest.cc",
"layers/layer_perftest.cc",
"layers/picture_layer_impl_perftest.cc",
"paint/paint_op_perftest.cc",
"raster/raster_buffer_provider_perftest.cc",
"raster/task_graph_runner_perftest.cc",
"raster/texture_compressor_perftest.cc",
Expand Down
174 changes: 174 additions & 0 deletions cc/paint/paint_op_perftest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <utility>

#include "base/test/launcher/unit_test_launcher.h"
#include "base/test/test_suite.h"
#include "cc/base/lap_timer.h"
#include "cc/paint/paint_op_buffer.h"
#include "cc/paint/paint_op_buffer_serializer.h"
#include "testing/perf/perf_test.h"
#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
#include "third_party/skia/include/effects/SkColorMatrixFilter.h"
#include "third_party/skia/include/effects/SkDashPathEffect.h"
#include "third_party/skia/include/effects/SkLayerDrawLooper.h"
#include "third_party/skia/include/effects/SkOffsetImageFilter.h"

namespace cc {
namespace {

static const int kTimeLimitMillis = 2000;
static const int kNumWarmupRuns = 20;
static const int kTimeCheckInterval = 1;

static const size_t kMaxSerializedBufferBytes = 100000;

class PaintOpPerfTest : public testing::Test {
public:
PaintOpPerfTest()
: timer_(kNumWarmupRuns,
base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
kTimeCheckInterval),
serialized_data_(static_cast<char*>(
base::AlignedAlloc(kMaxSerializedBufferBytes,
PaintOpBuffer::PaintOpAlign))),
deserialized_data_(static_cast<char*>(
base::AlignedAlloc(sizeof(LargestPaintOp),
PaintOpBuffer::PaintOpAlign))) {}

void RunTest(const std::string& name, const PaintOpBuffer& buffer) {
PaintOp::SerializeOptions serialize_options;
PaintOp::DeserializeOptions deserialize_options;

size_t bytes_written = 0u;
PaintOpBufferSerializer::Preamble preamble;

timer_.Reset();
do {
SimpleBufferSerializer serializer(serialized_data_.get(),
kMaxSerializedBufferBytes,
serialize_options.image_provider);
serializer.Serialize(&buffer, nullptr, preamble);
bytes_written = serializer.written();
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
CHECK_GT(bytes_written, 0u);

perf_test::PrintResult(name.c_str(), "", " serialize",
buffer.size() * timer_.LapsPerSecond(), "ops/s",
true);

size_t bytes_read = 0;
timer_.Reset();

do {
size_t remaining_read_bytes = bytes_written;
char* to_read = serialized_data_.get();

while (true) {
PaintOp* deserialized_op = PaintOp::Deserialize(
to_read, remaining_read_bytes, deserialized_data_.get(),
sizeof(LargestPaintOp), &bytes_read, deserialize_options);
deserialized_op->DestroyThis();

DCHECK_GE(remaining_read_bytes, bytes_read);
if (remaining_read_bytes == bytes_read)
break;

remaining_read_bytes -= bytes_read;
to_read += bytes_read;
timer_.NextLap();
}

timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());

perf_test::PrintResult(name.c_str(), "", "deserialize",
timer_.LapsPerSecond(), "ops/s", true);
}

protected:
LapTimer timer_;
std::unique_ptr<char, base::AlignedFreeDeleter> serialized_data_;
std::unique_ptr<char, base::AlignedFreeDeleter> deserialized_data_;
};

// Ops that can be memcopied both when serializing and deserializing.
TEST_F(PaintOpPerfTest, SimpleOps) {
PaintOpBuffer buffer;
for (size_t i = 0; i < 100; ++i)
buffer.push<ConcatOp>(SkMatrix::I());
RunTest("simple", buffer);
}

// Drawing ops with flags that don't have nested objects.
TEST_F(PaintOpPerfTest, DrawOps) {
PaintOpBuffer buffer;
PaintFlags flags;
for (size_t i = 0; i < 100; ++i)
buffer.push<DrawRectOp>(SkRect::MakeXYWH(1, 1, 1, 1), flags);
RunTest("draw", buffer);
}

// Ops with worst case flags.
TEST_F(PaintOpPerfTest, ManyFlagsOps) {
PaintOpBuffer buffer;

PaintFlags flags;
SkScalar intervals[] = {1.f, 1.f};
flags.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
flags.setMaskFilter(SkBlurMaskFilter::Make(SkBlurStyle::kOuter_SkBlurStyle,
4.3f, SkRect::MakeXYWH(1, 1, 1, 1),
kHigh_SkBlurQuality));
flags.setColorFilter(
SkColorMatrixFilter::MakeLightingFilter(SK_ColorYELLOW, SK_ColorGREEN));

SkLayerDrawLooper::Builder looper_builder;
looper_builder.addLayer();
looper_builder.addLayer(2.3f, 4.5f);
SkLayerDrawLooper::LayerInfo layer_info;
looper_builder.addLayer(layer_info);
flags.setLooper(looper_builder.detach());

sk_sp<PaintShader> shader = PaintShader::MakeColor(SK_ColorTRANSPARENT);
flags.setShader(std::move(shader));

SkPath path;
path.addCircle(2, 2, 5);
path.addCircle(3, 4, 2);
path.addArc(SkRect::MakeXYWH(1, 2, 3, 4), 5, 6);

for (size_t i = 0; i < 100; ++i)
buffer.push<DrawPathOp>(path, flags);
RunTest("flags", buffer);
}

// DrawTextBlobOps,
TEST_F(PaintOpPerfTest, TextOps) {
PaintOpBuffer buffer;

auto typeface = PaintTypeface::TestTypeface();

SkPaint font;
font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
font.setTypeface(typeface.ToSkTypeface());

SkTextBlobBuilder builder;
int glyph_count = 5;
SkRect rect = SkRect::MakeXYWH(1, 1, 1, 1);
const auto& run = builder.allocRun(font, glyph_count, 1.2f, 2.3f, &rect);
std::fill(run.glyphs, run.glyphs + glyph_count, 0);
std::vector<PaintTypeface> typefaces = {typeface};
auto blob = base::MakeRefCounted<PaintTextBlob>(builder.make(), typefaces);

PaintFlags flags;
for (size_t i = 0; i < 100; ++i)
buffer.push<DrawTextBlobOp>(blob, 0.f, 0.f, flags);

RunTest("text", buffer);
}

} // namespace
} // namespace cc

0 comments on commit eeb00f7

Please sign in to comment.