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

Unified Diff: src/gpu/GrResourceCache.h

Issue 2321563006: Make GrResourceCache dynamically change between LRU and random replacement strategies. (Closed)
Patch Set: rebase Created 4 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: src/gpu/GrResourceCache.h
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index bf7b237006b0fd270a1056744c130b5ce006be94..a481c222171a9ae4e71d09a0753233046879416a 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -13,7 +13,9 @@
#include "GrGpuResourcePriv.h"
#include "GrResourceCache.h"
#include "GrResourceKey.h"
+#include "SkChunkAlloc.h"
#include "SkMessageBus.h"
+#include "SkRandom.h"
#include "SkRefCnt.h"
#include "SkTArray.h"
#include "SkTDPQueue.h"
@@ -142,13 +144,7 @@ public:
/**
* Find a resource that matches a unique key.
*/
- GrGpuResource* findAndRefUniqueResource(const GrUniqueKey& key) {
- GrGpuResource* resource = fUniqueHash.find(key);
- if (resource) {
- this->refAndMakeResourceMRU(resource);
- }
- return resource;
- }
+ GrGpuResource* findAndRefUniqueResource(const GrUniqueKey& key);
/**
* Query whether a unique key exists in the cache.
@@ -159,14 +155,19 @@ public:
/** Purges resources to become under budget and processes resources with invalidated unique
keys. */
- void purgeAsNeeded();
+ void purgeAsNeeded() { this->internalPurgeAsNeeded(false); }
/** Purges all resources that don't have external owners. */
void purgeAllUnlocked();
/** Returns true if the cache would like a flush to occur in order to make more resources
purgeable. */
- bool requestsFlush() const { return fRequestFlush; }
+ bool requestsFlush() const {
+ // When in random replacement mode we request a flush in order to make as many resources
+ // as possible subject to replacement.
+ return this->overBudget() && (ReplacementStrategy::kRandom == fStrategy ||
+ 0 == fPurgeableQueue.count());
+ }
enum FlushType {
kExternal,
@@ -237,11 +238,15 @@ private:
void refAndMakeResourceMRU(GrGpuResource*);
/// @}
+ void internalPurgeAsNeeded(bool fromFlushNotification);
void resetFlushTimestamps();
void processInvalidUniqueKeys(const SkTArray<GrUniqueKeyInvalidatedMessage>&);
void addToNonpurgeableArray(GrGpuResource*);
void removeFromNonpurgeableArray(GrGpuResource*);
bool overBudget() const { return fBudgetedBytes > fMaxBytes || fBudgetedCount > fMaxCount; }
+ GrGpuResource* selectResourceUsingStrategy();
+ void recordPurgedKey(GrGpuResource*);
+ void recordKeyMiss(const GrUniqueKey&);
bool wouldFit(size_t bytes) {
return fBudgetedBytes+bytes <= fMaxBytes && fBudgetedCount+1 <= fMaxCount;
@@ -260,22 +265,27 @@ private:
class AvailableForScratchUse;
- struct ScratchMapTraits {
+ struct HashTraitsBase {
+ static uint32_t Hash(const GrResourceKey& key) { return key.hash(); }
+ };
+
+ struct ScratchMapTraits : public HashTraitsBase {
static const GrScratchKey& GetKey(const GrGpuResource& r) {
return r.resourcePriv().getScratchKey();
}
-
- static uint32_t Hash(const GrScratchKey& key) { return key.hash(); }
};
typedef SkTMultiMap<GrGpuResource, GrScratchKey, ScratchMapTraits> ScratchMap;
- struct UniqueHashTraits {
+ struct UniqueHashTraits : public HashTraitsBase {
static const GrUniqueKey& GetKey(const GrGpuResource& r) { return r.getUniqueKey(); }
-
- static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); }
};
typedef SkTDynamicHash<GrGpuResource, GrUniqueKey, UniqueHashTraits> UniqueHash;
robertphillips 2016/09/13 13:05:21 missing space before '{' ?
bsalomon 2016/09/13 13:31:33 Done.
+ struct UniqueSetTraits : public HashTraitsBase{
+ static const GrUniqueKey& GetKey(const GrUniqueKey& key) { return key; }
+ };
+ typedef SkTDynamicHash<GrUniqueKey, GrUniqueKey, UniqueSetTraits> UniqueKeySet;
+
static bool CompareTimestamp(GrGpuResource* const& a, GrGpuResource* const& b) {
return a->cacheAccess().timestamp() < b->cacheAccess().timestamp();
}
@@ -284,6 +294,22 @@ private:
return res->cacheAccess().accessCacheIndex();
}
+ /**
+ * The resource cache chooses one of these replacement strategies based on a "strategy score"
+ * updated after each external flush based on unique key cache misses.
+ */
+ enum class ReplacementStrategy {
+ kLRU,
+ kRandom
+ };
+ /**
+ * When the current strategy score is >=0 LRU is chosen, when it is < 0 random is chosen. The
+ * absolute value of the score moves by 1 each flush.
+ */
+ static constexpr int kStrategyScoreMin = -5;
+ static constexpr int kStrategyScoreMax = 4;
+ static constexpr int kInitialStrategyScoreMax = 3;
+
typedef SkMessageBus<GrUniqueKeyInvalidatedMessage>::Inbox InvalidUniqueKeyInbox;
typedef SkTDPQueue<GrGpuResource*, CompareTimestamp, AccessResourceIndex> PurgeableQueue;
typedef SkTDArray<GrGpuResource*> ResourceArray;
@@ -305,6 +331,16 @@ private:
size_t fMaxBytes;
int fMaxUnusedFlushes;
+ // Data related to replacement strategy.
+ SkRandom fRandom;
+ ReplacementStrategy fStrategy;
+ int fStrategyScore;
+ int fTotalMissesThisFlush;
+ int fMissesThisFlushPurgedRecently;
+ UniqueKeySet fUniqueKeysPurgedThisFlush[2];
+ SkChunkAlloc fUniqueKeysPurgedThisFlushStorage[2];
+ int fFlushParity;
+
#if GR_CACHE_STATS
int fHighWaterCount;
size_t fHighWaterBytes;
@@ -320,8 +356,6 @@ private:
int fBudgetedCount;
size_t fBudgetedBytes;
- bool fRequestFlush;
-
// We keep track of the "timestamps" of the last n flushes. If a resource hasn't been used in
// that time then we well preemptively purge it to reduce memory usage.
uint32_t* fFlushTimestamps;

Powered by Google App Engine
This is Rietveld 408576698