reduce mutex use and switch to spinlock
* Combine find and makeMRU. * Switch from SkMutex to SkSpinLock In the gm 'paragraph_$' this reduces acquiring the lock from 1.2% to 0.7% as measured by instruments and nanobench. Change-Id: I33e3af31825f175c9de42f001acf68ffe3623a8a Reviewed-on: https://skia-review.googlesource.com/c/skia/+/305564 Reviewed-by: Ben Wagner <bungeman@google.com> Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
parent
b6d4ad92ad
commit
13e3faebc6
@ -482,11 +482,7 @@ void GrRenderTargetContext::drawGlyphRunList(const GrClip* clip,
|
||||
}
|
||||
|
||||
const SkMatrix& drawMatrix(viewMatrix.localToDevice());
|
||||
if (blob != nullptr && blob->canReuse(blobPaint, blurRec, drawMatrix, drawOrigin)) {
|
||||
// Reusing the blob. Move it to the front of LRU cache.
|
||||
textBlobCache->makeMRU(blob.get());
|
||||
} else {
|
||||
// Build or Rebuild the GrTextBlob
|
||||
if (blob == nullptr || !blob->canReuse(blobPaint, blurRec, drawMatrix, drawOrigin)) {
|
||||
if (blob != nullptr) {
|
||||
// We have to remake the blob because changes may invalidate our masks.
|
||||
// TODO we could probably get away with reuse most of the time if the pointer is unique,
|
||||
|
@ -26,20 +26,30 @@ GrTextBlobCache::makeCachedBlob(const SkGlyphRunList& glyphRunList, const GrText
|
||||
const SkMatrix& viewMatrix) {
|
||||
sk_sp<GrTextBlob> cacheBlob(GrTextBlob::Make(glyphRunList, viewMatrix));
|
||||
cacheBlob->setupKey(key, blurRec, glyphRunList.paint());
|
||||
SkAutoMutexExclusive lock{fMutex};
|
||||
SkAutoSpinlock lock{fSpinLock};
|
||||
this->internalAdd(cacheBlob);
|
||||
glyphRunList.temporaryShuntBlobNotifyAddedToCache(fMessageBusID);
|
||||
return cacheBlob;
|
||||
}
|
||||
|
||||
sk_sp<GrTextBlob> GrTextBlobCache::find(const GrTextBlob::Key& key) const {
|
||||
SkAutoMutexExclusive lock{fMutex};
|
||||
const auto* idEntry = fBlobIDCache.find(key.fUniqueID);
|
||||
return idEntry ? idEntry->find(key) : nullptr;
|
||||
sk_sp<GrTextBlob> GrTextBlobCache::find(const GrTextBlob::Key& key) {
|
||||
SkAutoSpinlock lock{fSpinLock};
|
||||
const BlobIDCacheEntry* idEntry = fBlobIDCache.find(key.fUniqueID);
|
||||
if (idEntry == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<GrTextBlob> blob = idEntry->find(key);
|
||||
GrTextBlob* blobPtr = blob.get();
|
||||
if (blobPtr != nullptr && blobPtr != fBlobList.head()) {
|
||||
fBlobList.remove(blobPtr);
|
||||
fBlobList.addToHead(blobPtr);
|
||||
}
|
||||
return blob;
|
||||
}
|
||||
|
||||
void GrTextBlobCache::remove(GrTextBlob* blob) {
|
||||
SkAutoMutexExclusive lock{fMutex};
|
||||
SkAutoSpinlock lock{fSpinLock};
|
||||
this->internalRemove(blob);
|
||||
}
|
||||
|
||||
@ -56,18 +66,8 @@ void GrTextBlobCache::internalRemove(GrTextBlob* blob) {
|
||||
}
|
||||
}
|
||||
|
||||
void GrTextBlobCache::makeMRU(GrTextBlob* blob) {
|
||||
SkAutoMutexExclusive lock{fMutex};
|
||||
if (fBlobList.head() == blob) {
|
||||
return;
|
||||
}
|
||||
|
||||
fBlobList.remove(blob);
|
||||
fBlobList.addToHead(blob);
|
||||
}
|
||||
|
||||
void GrTextBlobCache::freeAll() {
|
||||
SkAutoMutexExclusive lock{fMutex};
|
||||
SkAutoSpinlock lock{fSpinLock};
|
||||
fBlobIDCache.reset();
|
||||
fBlobList.reset();
|
||||
fCurrentSize = 0;
|
||||
@ -79,7 +79,7 @@ void GrTextBlobCache::PostPurgeBlobMessage(uint32_t blobID, uint32_t cacheID) {
|
||||
}
|
||||
|
||||
void GrTextBlobCache::purgeStaleBlobs() {
|
||||
SkAutoMutexExclusive lock{fMutex};
|
||||
SkAutoSpinlock lock{fSpinLock};
|
||||
this->internalPurgeStaleBlobs();
|
||||
}
|
||||
|
||||
@ -106,12 +106,12 @@ void GrTextBlobCache::internalPurgeStaleBlobs() {
|
||||
}
|
||||
|
||||
size_t GrTextBlobCache::usedBytes() const {
|
||||
SkAutoMutexExclusive lock{fMutex};
|
||||
SkAutoSpinlock lock{fSpinLock};
|
||||
return fCurrentSize;
|
||||
}
|
||||
|
||||
bool GrTextBlobCache::isOverBudget() const {
|
||||
SkAutoMutexExclusive lock{fMutex};
|
||||
SkAutoSpinlock lock{fSpinLock};
|
||||
return fCurrentSize > fSizeBudget;
|
||||
}
|
||||
|
||||
|
@ -25,15 +25,13 @@ public:
|
||||
sk_sp<GrTextBlob> makeCachedBlob(const SkGlyphRunList& glyphRunList,
|
||||
const GrTextBlob::Key& key,
|
||||
const SkMaskFilterBase::BlurRec& blurRec,
|
||||
const SkMatrix& viewMatrix) SK_EXCLUDES(fMutex);
|
||||
const SkMatrix& viewMatrix) SK_EXCLUDES(fSpinLock);
|
||||
|
||||
sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) const SK_EXCLUDES(fMutex);
|
||||
sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) SK_EXCLUDES(fSpinLock);
|
||||
|
||||
void remove(GrTextBlob* blob) SK_EXCLUDES(fMutex);
|
||||
void remove(GrTextBlob* blob) SK_EXCLUDES(fSpinLock);
|
||||
|
||||
void makeMRU(GrTextBlob* blob) SK_EXCLUDES(fMutex);
|
||||
|
||||
void freeAll() SK_EXCLUDES(fMutex);
|
||||
void freeAll() SK_EXCLUDES(fSpinLock);
|
||||
|
||||
struct PurgeBlobMessage {
|
||||
PurgeBlobMessage(uint32_t blobID, uint32_t contextUniqueID)
|
||||
@ -45,11 +43,11 @@ public:
|
||||
|
||||
static void PostPurgeBlobMessage(uint32_t blobID, uint32_t cacheID);
|
||||
|
||||
void purgeStaleBlobs() SK_EXCLUDES(fMutex);
|
||||
void purgeStaleBlobs() SK_EXCLUDES(fSpinLock);
|
||||
|
||||
size_t usedBytes() const SK_EXCLUDES(fMutex);
|
||||
size_t usedBytes() const SK_EXCLUDES(fSpinLock);
|
||||
|
||||
bool isOverBudget() const SK_EXCLUDES(fMutex);
|
||||
bool isOverBudget() const SK_EXCLUDES(fSpinLock);
|
||||
|
||||
private:
|
||||
friend class GrTextBlobTestingPeer;
|
||||
@ -75,24 +73,24 @@ private:
|
||||
SkSTArray<1, sk_sp<GrTextBlob>> fBlobs;
|
||||
};
|
||||
|
||||
void internalPurgeStaleBlobs() SK_REQUIRES(fMutex);
|
||||
void internalPurgeStaleBlobs() SK_REQUIRES(fSpinLock);
|
||||
|
||||
void internalAdd(sk_sp<GrTextBlob> blob) SK_REQUIRES(fMutex);
|
||||
void internalRemove(GrTextBlob* blob) SK_REQUIRES(fMutex);
|
||||
void internalAdd(sk_sp<GrTextBlob> blob) SK_REQUIRES(fSpinLock);
|
||||
void internalRemove(GrTextBlob* blob) SK_REQUIRES(fSpinLock);
|
||||
|
||||
void internalCheckPurge(GrTextBlob* blob = nullptr) SK_REQUIRES(fMutex);
|
||||
void internalCheckPurge(GrTextBlob* blob = nullptr) SK_REQUIRES(fSpinLock);
|
||||
|
||||
static const int kDefaultBudget = 1 << 22;
|
||||
|
||||
mutable SkMutex fMutex;
|
||||
TextBlobList fBlobList SK_GUARDED_BY(fMutex);
|
||||
SkTHashMap<uint32_t, BlobIDCacheEntry> fBlobIDCache SK_GUARDED_BY(fMutex);
|
||||
size_t fSizeBudget SK_GUARDED_BY(fMutex);
|
||||
size_t fCurrentSize SK_GUARDED_BY(fMutex) {0};
|
||||
mutable SkSpinlock fSpinLock;
|
||||
TextBlobList fBlobList SK_GUARDED_BY(fSpinLock);
|
||||
SkTHashMap<uint32_t, BlobIDCacheEntry> fBlobIDCache SK_GUARDED_BY(fSpinLock);
|
||||
size_t fSizeBudget SK_GUARDED_BY(fSpinLock);
|
||||
size_t fCurrentSize SK_GUARDED_BY(fSpinLock) {0};
|
||||
|
||||
// In practice 'messageBusID' is always the unique ID of the owning GrContext
|
||||
const uint32_t fMessageBusID;
|
||||
SkMessageBus<PurgeBlobMessage>::Inbox fPurgeBlobInbox SK_GUARDED_BY(fMutex);
|
||||
SkMessageBus<PurgeBlobMessage>::Inbox fPurgeBlobInbox SK_GUARDED_BY(fSpinLock);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -55,7 +55,7 @@ static void setup_always_evict_atlas(GrDirectContext* dContext) {
|
||||
class GrTextBlobTestingPeer {
|
||||
public:
|
||||
static void SetBudget(GrTextBlobCache* cache, size_t budget) {
|
||||
SkAutoMutexExclusive lock{cache->fMutex};
|
||||
SkAutoSpinlock lock{cache->fSpinLock};
|
||||
cache->fSizeBudget = budget;
|
||||
cache->internalCheckPurge();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user