[graphite] Add debugging members for ResourceCache usage
Adds fields to gauge how fast resources are going through the return
queue, the purgeable queue, the proxy cache, and the upload buffer
manager. Hopefully this will help narrow down the cadence of when
resources are being requested and returned, and what type of resource
that is being accumulated to pathologic quantities.
Also updates the SkTMultiMap to track the size of values stored per
key to help identify distribution there.
Bug: b/407062399
Change-Id: Iae4aacec217ad12c1f290c46ad88081d0b6b4277
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1017376
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/core/SkTMultiMap.h b/src/core/SkTMultiMap.h
index c4df7c7..1c872b0 100644
--- a/src/core/SkTMultiMap.h
+++ b/src/core/SkTMultiMap.h
@@ -18,12 +18,16 @@
typename HashTraits=T>
class SkTMultiMap {
struct ValueList {
- explicit ValueList(T* value) : fValue(value), fNext(nullptr) {}
+ explicit ValueList(T* value) : fValue(value), fNext(nullptr), fCount(1) {}
static const Key& GetKey(const ValueList& e) { return HashTraits::GetKey(*e.fValue); }
static uint32_t Hash(const Key& key) { return HashTraits::Hash(key); }
T* fValue;
ValueList* fNext;
+
+ // TODO(b/407062399): Debugging information holding count of elements in ValueList.
+ // Only maintained in the head of the linked list to view in LLDB dumps.
+ uint32_t fCount;
};
public:
SkTMultiMap() : fCount(0) {}
@@ -56,6 +60,7 @@
// inserted value.
list->fNext = newEntry;
list->fValue = value;
+ list->fCount++;
} else {
fHash.add(new ValueList(value));
}
@@ -64,7 +69,8 @@
}
void remove(const Key& key, const T* value) {
- ValueList* list = fHash.find(key);
+ ValueList* root = fHash.find(key);
+ ValueList* list = root;
// Temporarily making this safe for remove entries not in the map because of
// crbug.com/877915.
#if 0
@@ -76,7 +82,7 @@
prev = list;
list = list->fNext;
}
- this->internalRemove(prev, list, key);
+ this->internalRemove(root, prev, list, key);
#else
ValueList* prev = nullptr;
while (list && list->fValue != value) {
@@ -86,7 +92,7 @@
// Crash in Debug since it'd be great to detect a repro of 877915.
SkASSERT(list);
if (list) {
- this->internalRemove(prev, list, key);
+ this->internalRemove(root, prev, list, key);
}
#endif
}
@@ -113,13 +119,14 @@
template<class FindPredicate>
T* findAndRemove(const Key& key, const FindPredicate f) {
- ValueList* list = fHash.find(key);
+ ValueList* root = fHash.find(key);
+ ValueList* list = root;
ValueList* prev = nullptr;
while (list) {
if (f(list->fValue)){
T* value = list->fValue;
- this->internalRemove(prev, list, key);
+ this->internalRemove(root, prev, list, key);
return value;
}
prev = list;
@@ -165,7 +172,8 @@
SkTDynamicHash<ValueList, Key> fHash;
int fCount;
- void internalRemove(ValueList* prev, ValueList* elem, const Key& key) {
+ void internalRemove(ValueList* root, ValueList* prev, ValueList* elem, const Key& key) {
+ root->fCount--;
if (elem->fNext) {
ValueList* next = elem->fNext;
elem->fValue = next->fValue;
diff --git a/src/gpu/graphite/ProxyCache.cpp b/src/gpu/graphite/ProxyCache.cpp
index 5b03aad..d3c346c 100644
--- a/src/gpu/graphite/ProxyCache.cpp
+++ b/src/gpu/graphite/ProxyCache.cpp
@@ -90,6 +90,8 @@
if (newEntry.fProxy) {
// Success, add it to the cache
fCache.set(key, newEntry);
+
+ fMaxProxyCacheSize = std::max(fMaxProxyCacheSize, fCache.count());
}
return newEntry.fProxy;
}
@@ -167,6 +169,7 @@
}
void ProxyCache::purgeAll() {
+ fMaxProxiesPurged = std::max(fMaxProxiesPurged, fCache.count());
// removeEntriesAndListeners() without having to copy out all of the keys
fCache.foreach([](const skgpu::UniqueKey&, const CacheEntry* entry) {
if (entry->fListener) {
@@ -221,6 +224,7 @@
}
});
+ fMaxProxiesPurgedUniquelyHeld = std::max(fMaxProxiesPurgedUniquelyHeld, toRemove.size());
this->removeEntriesAndListeners(toRemove);
}
@@ -238,6 +242,7 @@
}
});
+ fMaxProxiesPurgedNotUsedSince = std::max(fMaxProxiesPurgedNotUsedSince, toRemove.size());
this->removeEntriesAndListeners(toRemove);
}
diff --git a/src/gpu/graphite/ProxyCache.h b/src/gpu/graphite/ProxyCache.h
index 70969af..a989eaa 100644
--- a/src/gpu/graphite/ProxyCache.h
+++ b/src/gpu/graphite/ProxyCache.h
@@ -97,6 +97,13 @@
skia_private::THashMap<UniqueKey, CacheEntry, UniqueKeyHash> fCache;
SkMessageBus<UniqueKeyInvalidatedMsg_Graphite, uint32_t>::Inbox fInvalidUniqueKeyInbox;
+
+ // TODO(b/407062399): Debugging values to track how the ProxyCache behaves under pathologic
+ // situations.
+ int fMaxProxyCacheSize = 0;
+ int fMaxProxiesPurgedUniquelyHeld = 0;
+ int fMaxProxiesPurgedNotUsedSince = 0;
+ int fMaxProxiesPurged = 0;
};
} // namespace skgpu::graphite
diff --git a/src/gpu/graphite/ResourceCache.cpp b/src/gpu/graphite/ResourceCache.cpp
index 005f297..ef6336d 100644
--- a/src/gpu/graphite/ResourceCache.cpp
+++ b/src/gpu/graphite/ResourceCache.cpp
@@ -351,6 +351,7 @@
TRACE_EVENT_INSTANT1("skia.gpu.cache", TRACE_FUNC, TRACE_EVENT_SCOPE_THREAD,
"count", returnCount);
+ fMaxReturnQueueSize = std::max(returnCount, fMaxReturnQueueSize);
return returnCount > 0;
}
@@ -563,6 +564,10 @@
void ResourceCache::purgeAsNeeded() {
ASSERT_SINGLE_OWNER
+ int* tracker = this->overbudget() ? &fMaxPurgeableQueueSizePurgeAsNeededOverBudget
+ : &fMaxPurgeableQueueSizePurgeAsNeededUnderBudget;
+ *tracker = std::max(*tracker, fPurgeableQueue.count());
+
if (this->overbudget() && fProxyCache) {
fProxyCache->freeUniquelyHeld();
@@ -630,6 +635,8 @@
*resourcesToPurge.append() = resource;
}
+ fMaxResourcesToPurge = std::max(fMaxResourcesToPurge, resourcesToPurge.size());
+
// Delete the scratch resources. This must be done as a separate pass
// to avoid messing up the sorted order of the queue
for (int i = 0; i < resourcesToPurge.size(); i++) {
diff --git a/src/gpu/graphite/ResourceCache.h b/src/gpu/graphite/ResourceCache.h
index aedd26b..4458bdd 100644
--- a/src/gpu/graphite/ResourceCache.h
+++ b/src/gpu/graphite/ResourceCache.h
@@ -193,6 +193,13 @@
SingleOwner* fSingleOwner = nullptr;
SkDEBUGCODE(int fCount = 0;)
+
+ // TODO(b/407062399): Extra debugging fields that track the maximums of various resource
+ // processing phases to get an idea of how pathological scenarios arise.
+ int fMaxReturnQueueSize = 0;
+ int fMaxPurgeableQueueSizePurgeAsNeededUnderBudget = 0;
+ int fMaxPurgeableQueueSizePurgeAsNeededOverBudget = 0;
+ int fMaxResourcesToPurge = 0;
};
} // namespace skgpu::graphite
diff --git a/src/gpu/graphite/UploadBufferManager.cpp b/src/gpu/graphite/UploadBufferManager.cpp
index 2c6a6ff..7504789 100644
--- a/src/gpu/graphite/UploadBufferManager.cpp
+++ b/src/gpu/graphite/UploadBufferManager.cpp
@@ -88,6 +88,8 @@
fReusedBuffer = nullptr;
return {nullptr, BindBufferInfo()};
}
+
+ fReusedBufferCount++;
}
BindBufferInfo bindInfo;
@@ -105,6 +107,10 @@
}
void UploadBufferManager::transferToRecording(Recording* recording) {
+ fMaxReusedBufferCount = std::max(fMaxReusedBufferCount, fReusedBufferCount);
+ fMaxUsedBufferCount = std::max(fMaxUsedBufferCount, (int) fUsedBuffers.size());
+ fReusedBufferCount = 0;
+
for (sk_sp<Buffer>& buffer : fUsedBuffers) {
buffer->unmap();
recording->priv().addResourceRef(std::move(buffer));
@@ -118,6 +124,10 @@
}
void UploadBufferManager::transferToCommandBuffer(CommandBuffer* commandBuffer) {
+ fMaxReusedBufferCount = std::max(fMaxReusedBufferCount, fReusedBufferCount);
+ fMaxUsedBufferCount = std::max(fMaxUsedBufferCount, (int) fUsedBuffers.size());
+ fReusedBufferCount = 0;
+
for (sk_sp<Buffer>& buffer : fUsedBuffers) {
buffer->unmap();
commandBuffer->trackResource(std::move(buffer));
diff --git a/src/gpu/graphite/UploadBufferManager.h b/src/gpu/graphite/UploadBufferManager.h
index b050558..c80e873 100644
--- a/src/gpu/graphite/UploadBufferManager.h
+++ b/src/gpu/graphite/UploadBufferManager.h
@@ -52,6 +52,12 @@
uint32_t fReusedBufferOffset = 0;
std::vector<sk_sp<Buffer>> fUsedBuffers;
+
+ // TODO(b/407062399): Debugging fields to track pathologic resource situations
+ int fMaxReusedBufferCount = 0;
+ int fMaxUsedBufferCount = 0;
+
+ int fReusedBufferCount = 0; // reset after each transfer, should be less than fUsedBuffers.count
};
} // namespace skgpu::graphite