forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
oop: Add PaintOpBuffer serialization perf test
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
Showing
2 changed files
with
175 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |