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