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