1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2015 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkStrike.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "bench/Benchmark.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontMgr.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkGraphics.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/chromium/SkChromeRemoteGlyphCache.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkTLazy.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkStrikeSpec.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTaskGroup.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "tools/text/SkTextBlobTrace.h"
24*c8dee2aaSAndroid Build Coastguard Worker
25*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
26*c8dee2aaSAndroid Build Coastguard Worker
do_font_stuff(SkFont * font)27*c8dee2aaSAndroid Build Coastguard Worker static void do_font_stuff(SkFont* font) {
28*c8dee2aaSAndroid Build Coastguard Worker SkPaint defaultPaint;
29*c8dee2aaSAndroid Build Coastguard Worker for (SkScalar i = 8; i < 64; i++) {
30*c8dee2aaSAndroid Build Coastguard Worker font->setSize(i);
31*c8dee2aaSAndroid Build Coastguard Worker auto strikeSpec = SkStrikeSpec::MakeMask(
32*c8dee2aaSAndroid Build Coastguard Worker *font, defaultPaint, SkSurfaceProps(0, kUnknown_SkPixelGeometry),
33*c8dee2aaSAndroid Build Coastguard Worker SkScalerContextFlags::kNone, SkMatrix::I());
34*c8dee2aaSAndroid Build Coastguard Worker SkPackedGlyphID glyphs['z'];
35*c8dee2aaSAndroid Build Coastguard Worker for (int c = ' '; c < 'z'; c++) {
36*c8dee2aaSAndroid Build Coastguard Worker glyphs[c] = SkPackedGlyphID{font->unicharToGlyph(c)};
37*c8dee2aaSAndroid Build Coastguard Worker }
38*c8dee2aaSAndroid Build Coastguard Worker constexpr size_t glyphCount = 'z' - ' ';
39*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkPackedGlyphID> glyphIDs{&glyphs[SkTo<int>(' ')], glyphCount};
40*c8dee2aaSAndroid Build Coastguard Worker SkBulkGlyphMetricsAndImages images{strikeSpec};
41*c8dee2aaSAndroid Build Coastguard Worker for (int lookups = 0; lookups < 10; lookups++) {
42*c8dee2aaSAndroid Build Coastguard Worker (void)images.glyphs(glyphIDs);
43*c8dee2aaSAndroid Build Coastguard Worker }
44*c8dee2aaSAndroid Build Coastguard Worker }
45*c8dee2aaSAndroid Build Coastguard Worker }
46*c8dee2aaSAndroid Build Coastguard Worker
47*c8dee2aaSAndroid Build Coastguard Worker class SkGlyphCacheBasic : public Benchmark {
48*c8dee2aaSAndroid Build Coastguard Worker public:
SkGlyphCacheBasic(size_t cacheSize)49*c8dee2aaSAndroid Build Coastguard Worker explicit SkGlyphCacheBasic(size_t cacheSize) : fCacheSize(cacheSize) { }
50*c8dee2aaSAndroid Build Coastguard Worker
51*c8dee2aaSAndroid Build Coastguard Worker protected:
onGetName()52*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() override {
53*c8dee2aaSAndroid Build Coastguard Worker fName.printf("SkGlyphCacheBasic%dK", (int)(fCacheSize >> 10));
54*c8dee2aaSAndroid Build Coastguard Worker return fName.c_str();
55*c8dee2aaSAndroid Build Coastguard Worker }
56*c8dee2aaSAndroid Build Coastguard Worker
isSuitableFor(Backend backend)57*c8dee2aaSAndroid Build Coastguard Worker bool isSuitableFor(Backend backend) override {
58*c8dee2aaSAndroid Build Coastguard Worker return backend == Backend::kNonRendering;
59*c8dee2aaSAndroid Build Coastguard Worker }
60*c8dee2aaSAndroid Build Coastguard Worker
onDraw(int loops,SkCanvas *)61*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas*) override {
62*c8dee2aaSAndroid Build Coastguard Worker size_t oldCacheLimitSize = SkGraphics::GetFontCacheLimit();
63*c8dee2aaSAndroid Build Coastguard Worker SkGraphics::SetFontCacheLimit(fCacheSize);
64*c8dee2aaSAndroid Build Coastguard Worker SkFont font = ToolUtils::DefaultFont();
65*c8dee2aaSAndroid Build Coastguard Worker font.setEdging(SkFont::Edging::kAntiAlias);
66*c8dee2aaSAndroid Build Coastguard Worker font.setSubpixel(true);
67*c8dee2aaSAndroid Build Coastguard Worker font.setTypeface(ToolUtils::CreatePortableTypeface("serif", SkFontStyle::Italic()));
68*c8dee2aaSAndroid Build Coastguard Worker
69*c8dee2aaSAndroid Build Coastguard Worker for (int work = 0; work < loops; work++) {
70*c8dee2aaSAndroid Build Coastguard Worker do_font_stuff(&font);
71*c8dee2aaSAndroid Build Coastguard Worker }
72*c8dee2aaSAndroid Build Coastguard Worker SkGraphics::SetFontCacheLimit(oldCacheLimitSize);
73*c8dee2aaSAndroid Build Coastguard Worker }
74*c8dee2aaSAndroid Build Coastguard Worker
75*c8dee2aaSAndroid Build Coastguard Worker private:
76*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = Benchmark;
77*c8dee2aaSAndroid Build Coastguard Worker const size_t fCacheSize;
78*c8dee2aaSAndroid Build Coastguard Worker SkString fName;
79*c8dee2aaSAndroid Build Coastguard Worker };
80*c8dee2aaSAndroid Build Coastguard Worker
81*c8dee2aaSAndroid Build Coastguard Worker class SkGlyphCacheStressTest : public Benchmark {
82*c8dee2aaSAndroid Build Coastguard Worker public:
SkGlyphCacheStressTest(int cacheSize)83*c8dee2aaSAndroid Build Coastguard Worker explicit SkGlyphCacheStressTest(int cacheSize) : fCacheSize(cacheSize) { }
84*c8dee2aaSAndroid Build Coastguard Worker
85*c8dee2aaSAndroid Build Coastguard Worker protected:
onGetName()86*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() override {
87*c8dee2aaSAndroid Build Coastguard Worker fName.printf("SkGlyphCacheStressTest%dK", (int)(fCacheSize >> 10));
88*c8dee2aaSAndroid Build Coastguard Worker return fName.c_str();
89*c8dee2aaSAndroid Build Coastguard Worker }
90*c8dee2aaSAndroid Build Coastguard Worker
isSuitableFor(Backend backend)91*c8dee2aaSAndroid Build Coastguard Worker bool isSuitableFor(Backend backend) override {
92*c8dee2aaSAndroid Build Coastguard Worker return backend == Backend::kNonRendering;
93*c8dee2aaSAndroid Build Coastguard Worker }
94*c8dee2aaSAndroid Build Coastguard Worker
onDraw(int loops,SkCanvas *)95*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas*) override {
96*c8dee2aaSAndroid Build Coastguard Worker size_t oldCacheLimitSize = SkGraphics::GetFontCacheLimit();
97*c8dee2aaSAndroid Build Coastguard Worker SkGraphics::SetFontCacheLimit(fCacheSize);
98*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> typefaces[] = {
99*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::CreatePortableTypeface("serif", SkFontStyle::Italic()),
100*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::CreatePortableTypeface("sans-serif", SkFontStyle::Italic())};
101*c8dee2aaSAndroid Build Coastguard Worker
102*c8dee2aaSAndroid Build Coastguard Worker for (int work = 0; work < loops; work++) {
103*c8dee2aaSAndroid Build Coastguard Worker SkTaskGroup().batch(16, [&](int threadIndex) {
104*c8dee2aaSAndroid Build Coastguard Worker SkFont font = ToolUtils::DefaultFont();
105*c8dee2aaSAndroid Build Coastguard Worker font.setEdging(SkFont::Edging::kAntiAlias);
106*c8dee2aaSAndroid Build Coastguard Worker font.setSubpixel(true);
107*c8dee2aaSAndroid Build Coastguard Worker font.setTypeface(typefaces[threadIndex % 2]);
108*c8dee2aaSAndroid Build Coastguard Worker do_font_stuff(&font);
109*c8dee2aaSAndroid Build Coastguard Worker });
110*c8dee2aaSAndroid Build Coastguard Worker }
111*c8dee2aaSAndroid Build Coastguard Worker SkGraphics::SetFontCacheLimit(oldCacheLimitSize);
112*c8dee2aaSAndroid Build Coastguard Worker }
113*c8dee2aaSAndroid Build Coastguard Worker
114*c8dee2aaSAndroid Build Coastguard Worker private:
115*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = Benchmark;
116*c8dee2aaSAndroid Build Coastguard Worker const size_t fCacheSize;
117*c8dee2aaSAndroid Build Coastguard Worker SkString fName;
118*c8dee2aaSAndroid Build Coastguard Worker };
119*c8dee2aaSAndroid Build Coastguard Worker
120*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH( return new SkGlyphCacheBasic(256 * 1024); )
121*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH( return new SkGlyphCacheBasic(32 * 1024 * 1024); )
122*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH( return new SkGlyphCacheStressTest(256 * 1024); )
123*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH( return new SkGlyphCacheStressTest(32 * 1024 * 1024); )
124*c8dee2aaSAndroid Build Coastguard Worker
125*c8dee2aaSAndroid Build Coastguard Worker namespace {
126*c8dee2aaSAndroid Build Coastguard Worker class DiscardableManager : public SkStrikeServer::DiscardableHandleManager,
127*c8dee2aaSAndroid Build Coastguard Worker public SkStrikeClient::DiscardableHandleManager {
128*c8dee2aaSAndroid Build Coastguard Worker public:
DiscardableManager()129*c8dee2aaSAndroid Build Coastguard Worker DiscardableManager() { sk_bzero(&fCacheMissCount, sizeof(fCacheMissCount)); }
130*c8dee2aaSAndroid Build Coastguard Worker ~DiscardableManager() override = default;
131*c8dee2aaSAndroid Build Coastguard Worker
132*c8dee2aaSAndroid Build Coastguard Worker // Server implementation.
createHandle()133*c8dee2aaSAndroid Build Coastguard Worker SkDiscardableHandleId createHandle() override {
134*c8dee2aaSAndroid Build Coastguard Worker SkAutoMutexExclusive l(fMutex);
135*c8dee2aaSAndroid Build Coastguard Worker
136*c8dee2aaSAndroid Build Coastguard Worker // Handles starts as locked.
137*c8dee2aaSAndroid Build Coastguard Worker fLockedHandles.add(++fNextHandleId);
138*c8dee2aaSAndroid Build Coastguard Worker return fNextHandleId;
139*c8dee2aaSAndroid Build Coastguard Worker }
lockHandle(SkDiscardableHandleId id)140*c8dee2aaSAndroid Build Coastguard Worker bool lockHandle(SkDiscardableHandleId id) override {
141*c8dee2aaSAndroid Build Coastguard Worker SkAutoMutexExclusive l(fMutex);
142*c8dee2aaSAndroid Build Coastguard Worker
143*c8dee2aaSAndroid Build Coastguard Worker if (id <= fLastDeletedHandleId) return false;
144*c8dee2aaSAndroid Build Coastguard Worker fLockedHandles.add(id);
145*c8dee2aaSAndroid Build Coastguard Worker return true;
146*c8dee2aaSAndroid Build Coastguard Worker }
147*c8dee2aaSAndroid Build Coastguard Worker
148*c8dee2aaSAndroid Build Coastguard Worker // Client implementation.
deleteHandle(SkDiscardableHandleId id)149*c8dee2aaSAndroid Build Coastguard Worker bool deleteHandle(SkDiscardableHandleId id) override {
150*c8dee2aaSAndroid Build Coastguard Worker SkAutoMutexExclusive l(fMutex);
151*c8dee2aaSAndroid Build Coastguard Worker
152*c8dee2aaSAndroid Build Coastguard Worker return id <= fLastDeletedHandleId;
153*c8dee2aaSAndroid Build Coastguard Worker }
154*c8dee2aaSAndroid Build Coastguard Worker
notifyCacheMiss(SkStrikeClient::CacheMissType type,int fontSize)155*c8dee2aaSAndroid Build Coastguard Worker void notifyCacheMiss(SkStrikeClient::CacheMissType type, int fontSize) override {
156*c8dee2aaSAndroid Build Coastguard Worker SkAutoMutexExclusive l(fMutex);
157*c8dee2aaSAndroid Build Coastguard Worker
158*c8dee2aaSAndroid Build Coastguard Worker fCacheMissCount[type]++;
159*c8dee2aaSAndroid Build Coastguard Worker }
isHandleDeleted(SkDiscardableHandleId id)160*c8dee2aaSAndroid Build Coastguard Worker bool isHandleDeleted(SkDiscardableHandleId id) override {
161*c8dee2aaSAndroid Build Coastguard Worker SkAutoMutexExclusive l(fMutex);
162*c8dee2aaSAndroid Build Coastguard Worker
163*c8dee2aaSAndroid Build Coastguard Worker return id <= fLastDeletedHandleId;
164*c8dee2aaSAndroid Build Coastguard Worker }
165*c8dee2aaSAndroid Build Coastguard Worker
unlockAll()166*c8dee2aaSAndroid Build Coastguard Worker void unlockAll() {
167*c8dee2aaSAndroid Build Coastguard Worker SkAutoMutexExclusive l(fMutex);
168*c8dee2aaSAndroid Build Coastguard Worker
169*c8dee2aaSAndroid Build Coastguard Worker fLockedHandles.reset();
170*c8dee2aaSAndroid Build Coastguard Worker }
unlockAndDeleteAll()171*c8dee2aaSAndroid Build Coastguard Worker void unlockAndDeleteAll() {
172*c8dee2aaSAndroid Build Coastguard Worker SkAutoMutexExclusive l(fMutex);
173*c8dee2aaSAndroid Build Coastguard Worker
174*c8dee2aaSAndroid Build Coastguard Worker fLockedHandles.reset();
175*c8dee2aaSAndroid Build Coastguard Worker fLastDeletedHandleId = fNextHandleId;
176*c8dee2aaSAndroid Build Coastguard Worker }
lockedHandles() const177*c8dee2aaSAndroid Build Coastguard Worker const THashSet<SkDiscardableHandleId>& lockedHandles() const {
178*c8dee2aaSAndroid Build Coastguard Worker SkAutoMutexExclusive l(fMutex);
179*c8dee2aaSAndroid Build Coastguard Worker
180*c8dee2aaSAndroid Build Coastguard Worker return fLockedHandles;
181*c8dee2aaSAndroid Build Coastguard Worker }
handleCount()182*c8dee2aaSAndroid Build Coastguard Worker SkDiscardableHandleId handleCount() {
183*c8dee2aaSAndroid Build Coastguard Worker SkAutoMutexExclusive l(fMutex);
184*c8dee2aaSAndroid Build Coastguard Worker
185*c8dee2aaSAndroid Build Coastguard Worker return fNextHandleId;
186*c8dee2aaSAndroid Build Coastguard Worker }
cacheMissCount(uint32_t type)187*c8dee2aaSAndroid Build Coastguard Worker int cacheMissCount(uint32_t type) {
188*c8dee2aaSAndroid Build Coastguard Worker SkAutoMutexExclusive l(fMutex);
189*c8dee2aaSAndroid Build Coastguard Worker
190*c8dee2aaSAndroid Build Coastguard Worker return fCacheMissCount[type];
191*c8dee2aaSAndroid Build Coastguard Worker }
hasCacheMiss() const192*c8dee2aaSAndroid Build Coastguard Worker bool hasCacheMiss() const {
193*c8dee2aaSAndroid Build Coastguard Worker SkAutoMutexExclusive l(fMutex);
194*c8dee2aaSAndroid Build Coastguard Worker
195*c8dee2aaSAndroid Build Coastguard Worker for (uint32_t i = 0; i <= SkStrikeClient::CacheMissType::kLast; ++i) {
196*c8dee2aaSAndroid Build Coastguard Worker if (fCacheMissCount[i] > 0) return true;
197*c8dee2aaSAndroid Build Coastguard Worker }
198*c8dee2aaSAndroid Build Coastguard Worker return false;
199*c8dee2aaSAndroid Build Coastguard Worker }
resetCacheMissCounts()200*c8dee2aaSAndroid Build Coastguard Worker void resetCacheMissCounts() {
201*c8dee2aaSAndroid Build Coastguard Worker SkAutoMutexExclusive l(fMutex);
202*c8dee2aaSAndroid Build Coastguard Worker sk_bzero(&fCacheMissCount, sizeof(fCacheMissCount));
203*c8dee2aaSAndroid Build Coastguard Worker }
204*c8dee2aaSAndroid Build Coastguard Worker
205*c8dee2aaSAndroid Build Coastguard Worker private:
206*c8dee2aaSAndroid Build Coastguard Worker // The tests below run in parallel on multiple threads and use the same
207*c8dee2aaSAndroid Build Coastguard Worker // process global SkStrikeCache. So the implementation needs to be
208*c8dee2aaSAndroid Build Coastguard Worker // thread-safe.
209*c8dee2aaSAndroid Build Coastguard Worker mutable SkMutex fMutex;
210*c8dee2aaSAndroid Build Coastguard Worker
211*c8dee2aaSAndroid Build Coastguard Worker SkDiscardableHandleId fNextHandleId = 0u;
212*c8dee2aaSAndroid Build Coastguard Worker SkDiscardableHandleId fLastDeletedHandleId = 0u;
213*c8dee2aaSAndroid Build Coastguard Worker THashSet<SkDiscardableHandleId> fLockedHandles;
214*c8dee2aaSAndroid Build Coastguard Worker int fCacheMissCount[SkStrikeClient::CacheMissType::kLast + 1u];
215*c8dee2aaSAndroid Build Coastguard Worker };
216*c8dee2aaSAndroid Build Coastguard Worker
217*c8dee2aaSAndroid Build Coastguard Worker class DiffCanvasBench : public Benchmark {
218*c8dee2aaSAndroid Build Coastguard Worker SkString fBenchName;
219*c8dee2aaSAndroid Build Coastguard Worker std::function<std::unique_ptr<SkStreamAsset>()> fDataProvider;
220*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkTextBlobTrace::Record> fTrace;
221*c8dee2aaSAndroid Build Coastguard Worker sk_sp<DiscardableManager> fDiscardableManager;
222*c8dee2aaSAndroid Build Coastguard Worker SkTLazy<SkStrikeServer> fServer;
223*c8dee2aaSAndroid Build Coastguard Worker
onGetName()224*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() override { return fBenchName.c_str(); }
225*c8dee2aaSAndroid Build Coastguard Worker
isSuitableFor(Backend b)226*c8dee2aaSAndroid Build Coastguard Worker bool isSuitableFor(Backend b) override { return b == Backend::kNonRendering; }
227*c8dee2aaSAndroid Build Coastguard Worker
onDraw(int loops,SkCanvas * modelCanvas)228*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas* modelCanvas) override {
229*c8dee2aaSAndroid Build Coastguard Worker SkSurfaceProps props;
230*c8dee2aaSAndroid Build Coastguard Worker if (modelCanvas) { modelCanvas->getProps(&props); }
231*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCanvas> canvas = fServer->makeAnalysisCanvas(1024, 1024, props,
232*c8dee2aaSAndroid Build Coastguard Worker nullptr, true, true);
233*c8dee2aaSAndroid Build Coastguard Worker loops *= 100;
234*c8dee2aaSAndroid Build Coastguard Worker while (loops --> 0) {
235*c8dee2aaSAndroid Build Coastguard Worker for (const auto& record : fTrace) {
236*c8dee2aaSAndroid Build Coastguard Worker canvas->drawTextBlob(
237*c8dee2aaSAndroid Build Coastguard Worker record.blob.get(), record.offset.x(), record.offset.y(),record.paint);
238*c8dee2aaSAndroid Build Coastguard Worker }
239*c8dee2aaSAndroid Build Coastguard Worker }
240*c8dee2aaSAndroid Build Coastguard Worker }
241*c8dee2aaSAndroid Build Coastguard Worker
onDelayedSetup()242*c8dee2aaSAndroid Build Coastguard Worker void onDelayedSetup() override {
243*c8dee2aaSAndroid Build Coastguard Worker auto stream = fDataProvider();
244*c8dee2aaSAndroid Build Coastguard Worker fDiscardableManager = sk_make_sp<DiscardableManager>();
245*c8dee2aaSAndroid Build Coastguard Worker fServer.init(fDiscardableManager.get());
246*c8dee2aaSAndroid Build Coastguard Worker fTrace = SkTextBlobTrace::CreateBlobTrace(stream.get(), nullptr);
247*c8dee2aaSAndroid Build Coastguard Worker }
248*c8dee2aaSAndroid Build Coastguard Worker
249*c8dee2aaSAndroid Build Coastguard Worker public:
DiffCanvasBench(SkString n,std::function<std::unique_ptr<SkStreamAsset> ()> f)250*c8dee2aaSAndroid Build Coastguard Worker DiffCanvasBench(SkString n, std::function<std::unique_ptr<SkStreamAsset>()> f)
251*c8dee2aaSAndroid Build Coastguard Worker : fBenchName(std::move(n)), fDataProvider(std::move(f)) {}
252*c8dee2aaSAndroid Build Coastguard Worker };
253*c8dee2aaSAndroid Build Coastguard Worker } // namespace
254*c8dee2aaSAndroid Build Coastguard Worker
CreateDiffCanvasBench(SkString name,std::function<std::unique_ptr<SkStreamAsset> ()> dataSrc)255*c8dee2aaSAndroid Build Coastguard Worker Benchmark* CreateDiffCanvasBench(
256*c8dee2aaSAndroid Build Coastguard Worker SkString name, std::function<std::unique_ptr<SkStreamAsset>()> dataSrc) {
257*c8dee2aaSAndroid Build Coastguard Worker return new DiffCanvasBench(std::move(name), std::move(dataSrc));
258*c8dee2aaSAndroid Build Coastguard Worker }
259*c8dee2aaSAndroid Build Coastguard Worker
260*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH( return CreateDiffCanvasBench(
261*c8dee2aaSAndroid Build Coastguard Worker SkString("SkDiffBench-lorem_ipsum"),
__anond70192340302()262*c8dee2aaSAndroid Build Coastguard Worker [](){ return GetResourceAsStream("diff_canvas_traces/lorem_ipsum.trace"); }));
263