Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Side by Side Diff: src/core/SkGlyphCache.cpp

Issue 877113002: use murmur3 finisher to improve font hash efficiency (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1
2 /* 1 /*
3 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
4 * 3 *
5 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 5 * found in the LICENSE file.
7 */ 6 */
8 7
9
10 #include "SkGlyphCache.h" 8 #include "SkGlyphCache.h"
11 #include "SkGlyphCache_Globals.h" 9 #include "SkGlyphCache_Globals.h"
12 #include "SkGraphics.h" 10 #include "SkGraphics.h"
13 #include "SkLazyPtr.h" 11 #include "SkLazyPtr.h"
14 #include "SkPaint.h" 12 #include "SkPaint.h"
15 #include "SkPath.h" 13 #include "SkPath.h"
16 #include "SkTemplates.h" 14 #include "SkTemplates.h"
17 #include "SkTLS.h" 15 #include "SkTLS.h"
18 #include "SkTypeface.h" 16 #include "SkTypeface.h"
19 17
20 //#define SPEW_PURGE_STATUS 18 //#define SPEW_PURGE_STATUS
21 //#define RECORD_HASH_EFFICIENCY
22 19
23 namespace { 20 namespace {
24 21
25 SkGlyphCache_Globals* create_globals() { 22 SkGlyphCache_Globals* create_globals() {
26 return SkNEW_ARGS(SkGlyphCache_Globals, (SkGlyphCache_Globals::kYes_UseMutex )); 23 return SkNEW_ARGS(SkGlyphCache_Globals, (SkGlyphCache_Globals::kYes_UseMutex ));
27 } 24 }
28 25
29 } // namespace 26 } // namespace
30 27
31 SK_DECLARE_STATIC_LAZY_PTR(SkGlyphCache_Globals, globals, create_globals); 28 SK_DECLARE_STATIC_LAZY_PTR(SkGlyphCache_Globals, globals, create_globals);
32 29
33 // Returns the shared globals 30 // Returns the shared globals
34 static SkGlyphCache_Globals& getSharedGlobals() { 31 static SkGlyphCache_Globals& getSharedGlobals() {
35 return *globals.get(); 32 return *globals.get();
36 } 33 }
37 34
38 // Returns the TLS globals (if set), or the shared globals 35 // Returns the TLS globals (if set), or the shared globals
39 static SkGlyphCache_Globals& getGlobals() { 36 static SkGlyphCache_Globals& getGlobals() {
40 SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS(); 37 SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS();
41 return tls ? *tls : getSharedGlobals(); 38 return tls ? *tls : getSharedGlobals();
42 } 39 }
43 40
44 /////////////////////////////////////////////////////////////////////////////// 41 ///////////////////////////////////////////////////////////////////////////////
45 42
46 #ifdef RECORD_HASH_EFFICIENCY 43 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
47 static uint32_t gHashSuccess; 44 #define RecordHashSuccess() fHashHitCount += 1
48 static uint32_t gHashCollision; 45 #define RecordHashCollisionIf(pred) do { if (pred) fHashMissCount += 1; } while (0)
49
50 static void RecordHashSuccess() {
51 gHashSuccess += 1;
52 }
53
54 static void RecordHashCollisionIf(bool pred) {
55 if (pred) {
56 gHashCollision += 1;
57
58 uint32_t total = gHashSuccess + gHashCollision;
59 SkDebugf("Font Cache Hash success rate: %d%%\n",
60 100 * gHashSuccess / total);
61 }
62 }
63 #else 46 #else
64 #define RecordHashSuccess() (void)0 47 #define RecordHashSuccess() (void)0
65 #define RecordHashCollisionIf(pred) (void)0 48 #define RecordHashCollisionIf(pred) (void)0
66 #endif 49 #endif
67 #define RecordHashCollision() RecordHashCollisionIf(true) 50 #define RecordHashCollision() RecordHashCollisionIf(true)
68 51
69 /////////////////////////////////////////////////////////////////////////////// 52 ///////////////////////////////////////////////////////////////////////////////
70 53
71 // so we don't grow our arrays a lot 54 // so we don't grow our arrays a lot
72 #define kMinGlyphCount 16 55 #define kMinGlyphCount 16
73 #define kMinGlyphImageSize (16*2) 56 #define kMinGlyphImageSize (16*2)
74 #define kMinAllocAmount ((sizeof(SkGlyph) + kMinGlyphImageSize) * kMinGlyphC ount) 57 #define kMinAllocAmount ((sizeof(SkGlyph) + kMinGlyphImageSize) * kMinGlyphC ount)
75 58
(...skipping 11 matching lines...) Expand all
87 // init to 0 so that all of the pointers will be null 70 // init to 0 so that all of the pointers will be null
88 memset(fGlyphHash, 0, sizeof(fGlyphHash)); 71 memset(fGlyphHash, 0, sizeof(fGlyphHash));
89 // init with 0xFF so that the charCode field will be -1, which is invalid 72 // init with 0xFF so that the charCode field will be -1, which is invalid
90 memset(fCharToGlyphHash, 0xFF, sizeof(fCharToGlyphHash)); 73 memset(fCharToGlyphHash, 0xFF, sizeof(fCharToGlyphHash));
91 74
92 fMemoryUsed = sizeof(*this); 75 fMemoryUsed = sizeof(*this);
93 76
94 fGlyphArray.setReserve(kMinGlyphCount); 77 fGlyphArray.setReserve(kMinGlyphCount);
95 78
96 fAuxProcList = NULL; 79 fAuxProcList = NULL;
80
81 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
82 fHashHitCount = fHashMissCount = 1;
mtklein 2015/01/27 17:10:12 0?
reed1 2015/01/27 18:33:33 Yea, OK. That will make it more complicated for me
83 #endif
97 } 84 }
98 85
99 SkGlyphCache::~SkGlyphCache() { 86 SkGlyphCache::~SkGlyphCache() {
100 #if 0 87 #if 0
101 { 88 {
102 size_t ptrMem = fGlyphArray.count() * sizeof(SkGlyph*); 89 size_t ptrMem = fGlyphArray.count() * sizeof(SkGlyph*);
103 size_t glyphAlloc = fGlyphAlloc.totalCapacity(); 90 size_t glyphAlloc = fGlyphAlloc.totalCapacity();
104 size_t glyphHashUsed = 0; 91 size_t glyphHashUsed = 0;
105 size_t uniHashUsed = 0; 92 size_t uniHashUsed = 0;
106 for (int i = 0; i < kHashCount; ++i) { 93 for (int i = 0; i < kHashCount; ++i) {
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 } else { 240 } else {
254 RecordHashSuccess(); 241 RecordHashSuccess();
255 if (glyph->isJustAdvance()) { 242 if (glyph->isJustAdvance()) {
256 fScalerContext->getMetrics(glyph); 243 fScalerContext->getMetrics(glyph);
257 } 244 }
258 } 245 }
259 SkASSERT(glyph->isFullMetrics()); 246 SkASSERT(glyph->isFullMetrics());
260 return *glyph; 247 return *glyph;
261 } 248 }
262 249
263 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, 250 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFi xed y) {
264 SkFixed x, SkFixed y) {
265 VALIDATE(); 251 VALIDATE();
266 uint32_t id = SkGlyph::MakeID(glyphID, x, y); 252 uint32_t id = SkGlyph::MakeID(glyphID, x, y);
267 unsigned index = ID2HashIndex(id); 253 unsigned index = ID2HashIndex(id);
268 SkGlyph* glyph = fGlyphHash[index]; 254 SkGlyph* glyph = fGlyphHash[index];
269 255
270 if (NULL == glyph || glyph->fID != id) { 256 if (NULL == glyph || glyph->fID != id) {
271 RecordHashCollisionIf(glyph != NULL); 257 RecordHashCollisionIf(glyph != NULL);
272 glyph = this->lookupMetrics(id, kFull_MetricsType); 258 glyph = this->lookupMetrics(id, kFull_MetricsType);
273 fGlyphHash[index] = glyph; 259 fGlyphHash[index] = glyph;
274 } else { 260 } else {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 if (glyph.fPath == NULL) { 343 if (glyph.fPath == NULL) {
358 const_cast<SkGlyph&>(glyph).fPath = SkNEW(SkPath); 344 const_cast<SkGlyph&>(glyph).fPath = SkNEW(SkPath);
359 fScalerContext->getPath(glyph, glyph.fPath); 345 fScalerContext->getPath(glyph, glyph.fPath);
360 fMemoryUsed += sizeof(SkPath) + 346 fMemoryUsed += sizeof(SkPath) +
361 glyph.fPath->countPoints() * sizeof(SkPoint); 347 glyph.fPath->countPoints() * sizeof(SkPoint);
362 } 348 }
363 } 349 }
364 return glyph.fPath; 350 return glyph.fPath;
365 } 351 }
366 352
353 void SkGlyphCache::dump() const {
354 const SkTypeface* face = fScalerContext->getTypeface();
355 const SkScalerContextRec& rec = fScalerContext->getRec();
356 SkMatrix matrix;
357 rec.getSingleMatrixWithoutTextSize(&matrix);
358 SkString name;
359 face->getFamilyName(&name);
360
361 SkString msg;
362 msg.printf("cache typeface:%x %25s:%d size:%2g [%g %g %g %g] lum:%02X devG:% d pntG:%d cntr:%d glyphs:%3d",
363 face->uniqueID(), name.c_str(), face->style(), rec.fTextSize,
364 matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewX],
365 matrix[SkMatrix::kMSkewY], matrix[SkMatrix::kMScaleY],
366 rec.fLumBits & 0xFF, rec.fDeviceGamma, rec.fPaintGamma, rec.fCont rast,
367 fGlyphArray.count());
368 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
369 msg.appendf(" hash:%2d\n", 100 * fHashHitCount / (fHashHitCount + fHashMissC ount));
370 #endif
371 SkDebugf("%s\n", msg.c_str());
372 }
373
367 /////////////////////////////////////////////////////////////////////////////// 374 ///////////////////////////////////////////////////////////////////////////////
368 375
369 bool SkGlyphCache::getAuxProcData(void (*proc)(void*), void** dataPtr) const { 376 bool SkGlyphCache::getAuxProcData(void (*proc)(void*), void** dataPtr) const {
370 const AuxProcRec* rec = fAuxProcList; 377 const AuxProcRec* rec = fAuxProcList;
371 while (rec) { 378 while (rec) {
372 if (rec->fProc == proc) { 379 if (rec->fProc == proc) {
373 if (dataPtr) { 380 if (dataPtr) {
374 *dataPtr = rec->fData; 381 *dataPtr = rec->fData;
375 } 382 }
376 return true; 383 return true;
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 return cache; 520 return cache;
514 } 521 }
515 522
516 void SkGlyphCache::AttachCache(SkGlyphCache* cache) { 523 void SkGlyphCache::AttachCache(SkGlyphCache* cache) {
517 SkASSERT(cache); 524 SkASSERT(cache);
518 SkASSERT(cache->fNext == NULL); 525 SkASSERT(cache->fNext == NULL);
519 526
520 getGlobals().attachCacheToHead(cache); 527 getGlobals().attachCacheToHead(cache);
521 } 528 }
522 529
530 void SkGlyphCache::Dump() {
531 SkGlyphCache_Globals& globals = getGlobals();
532 SkAutoMutexAcquire ac(globals.fMutex);
533 SkGlyphCache* cache;
534
535 globals.validate();
536
537 SkDebugf("SkGlyphCache strikes:%d memory:%d\n",
538 globals.getCacheCountUsed(), (int)globals.getTotalMemoryUsed());
539
540 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
541 int hitCount = 0;
542 int missCount = 0;
543 #endif
544
545 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) {
546 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
547 hitCount += cache->fHashHitCount;
548 missCount += cache->fHashMissCount;
549 #endif
550 cache->dump();
551 }
552 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
553 SkDebugf("Hash hit percent:%2d\n", 100 * hitCount / (hitCount + missCount));
554 #endif
555 }
556
523 /////////////////////////////////////////////////////////////////////////////// 557 ///////////////////////////////////////////////////////////////////////////////
524 558
525 void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) { 559 void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) {
526 SkAutoMutexAcquire ac(fMutex); 560 SkAutoMutexAcquire ac(fMutex);
527 561
528 this->validate(); 562 this->validate();
529 cache->validate(); 563 cache->validate();
530 564
531 this->internalAttachCacheToHead(cache); 565 this->internalAttachCacheToHead(cache);
532 this->internalPurge(); 566 this->internalPurge();
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 return tls ? tls->getCacheSizeLimit() : 0; 735 return tls ? tls->getCacheSizeLimit() : 0;
702 } 736 }
703 737
704 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { 738 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) {
705 if (0 == bytes) { 739 if (0 == bytes) {
706 SkGlyphCache_Globals::DeleteTLS(); 740 SkGlyphCache_Globals::DeleteTLS();
707 } else { 741 } else {
708 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes); 742 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes);
709 } 743 }
710 } 744 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698