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

Side by Side Diff: src/gpu/GrResourceCache.h

Issue 91453002: Speed up GrResourceCache add and lookup by using TDynamicHash (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years 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 | Annotate | Revision Log
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2011 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 10
11 #ifndef GrResourceCache_DEFINED 11 #ifndef GrResourceCache_DEFINED
12 #define GrResourceCache_DEFINED 12 #define GrResourceCache_DEFINED
13 13
14 #include "GrConfig.h" 14 #include "GrConfig.h"
15 #include "GrTypes.h" 15 #include "GrTypes.h"
16 #include "GrTHashTable.h"
17 #include "GrBinHashKey.h" 16 #include "GrBinHashKey.h"
17 #include "GrResource.h"
18 #include "SkMessageBus.h" 18 #include "SkMessageBus.h"
19 #include "SkTDynamicHash.h"
19 #include "SkTInternalLList.h" 20 #include "SkTInternalLList.h"
20 21
21 class GrResource;
22 class GrResourceEntry; 22 class GrResourceEntry;
23 23
24 class GrResourceKey { 24 class GrResourceKey {
25 public: 25 public:
26 enum {
27 kHashBits = 7,
28 kHashCount = 1 << kHashBits,
29 kHashMask = kHashCount - 1
30 };
31
32 static GrCacheID::Domain ScratchDomain() { 26 static GrCacheID::Domain ScratchDomain() {
33 static const GrCacheID::Domain gDomain = GrCacheID::GenerateDomain(); 27 static const GrCacheID::Domain gDomain = GrCacheID::GenerateDomain();
34 return gDomain; 28 return gDomain;
35 } 29 }
36 30
37 /** Uniquely identifies the GrResource subclass in the key to avoid collisio ns 31 /** Uniquely identifies the GrResource subclass in the key to avoid collisio ns
38 across resource types. */ 32 across resource types. */
39 typedef uint8_t ResourceType; 33 typedef uint8_t ResourceType;
40 34
41 /** Flags set by the GrResource subclass. */ 35 /** Flags set by the GrResource subclass. */
(...skipping 12 matching lines...) Expand all
54 } 48 }
55 49
56 GrResourceKey() { 50 GrResourceKey() {
57 fKey.reset(); 51 fKey.reset();
58 } 52 }
59 53
60 void reset(const GrCacheID& id, ResourceType type, ResourceFlags flags) { 54 void reset(const GrCacheID& id, ResourceType type, ResourceFlags flags) {
61 this->init(id.getDomain(), id.getKey(), type, flags); 55 this->init(id.getDomain(), id.getKey(), type, flags);
62 } 56 }
63 57
64 //!< returns hash value [0..kHashMask] for the key 58 uint32_t getHash() const {
65 int getHash() const { 59 return fKey.getHash();
66 return fKey.getHash() & kHashMask;
67 } 60 }
68 61
69 bool isScratch() const { 62 bool isScratch() const {
70 return ScratchDomain() == 63 return ScratchDomain() ==
71 *reinterpret_cast<const GrCacheID::Domain*>(fKey.getData() + 64 *reinterpret_cast<const GrCacheID::Domain*>(fKey.getData() +
72 kCacheIDDomainOffset); 65 kCacheIDDomainOffset);
73 } 66 }
74 67
75 ResourceType getResourceType() const { 68 ResourceType getResourceType() const {
76 return *reinterpret_cast<const ResourceType*>(fKey.getData() + 69 return *reinterpret_cast<const ResourceType*>(fKey.getData() +
77 kResourceTypeOffset); 70 kResourceTypeOffset);
78 } 71 }
79 72
80 ResourceFlags getResourceFlags() const { 73 ResourceFlags getResourceFlags() const {
81 return *reinterpret_cast<const ResourceFlags*>(fKey.getData() + 74 return *reinterpret_cast<const ResourceFlags*>(fKey.getData() +
82 kResourceFlagsOffset); 75 kResourceFlagsOffset);
83 } 76 }
84 77
85 bool operator==(const GrResourceKey& other) const { return fKey == other.fKe y; } 78 bool operator==(const GrResourceKey& other) const { return fKey == other.fKe y; }
86 bool operator<(const GrResourceKey& other) const { return fKey < other.fKey; }
87
88 static bool LessThan(const GrResourceEntry& entry, const GrResourceKey& key) ;
89 static bool Equals(const GrResourceEntry& entry, const GrResourceKey& key);
90 #ifdef SK_DEBUG
91 static bool LessThan(const GrResourceEntry& a, const GrResourceEntry& b);
92 static bool Equals(const GrResourceEntry& a, const GrResourceEntry& b);
93 #endif
94 79
95 private: 80 private:
96 enum { 81 enum {
97 kCacheIDKeyOffset = 0, 82 kCacheIDKeyOffset = 0,
98 kCacheIDDomainOffset = kCacheIDKeyOffset + sizeof(GrCacheID::Key), 83 kCacheIDDomainOffset = kCacheIDKeyOffset + sizeof(GrCacheID::Key),
99 kResourceTypeOffset = kCacheIDDomainOffset + sizeof(GrCacheID::Domain), 84 kResourceTypeOffset = kCacheIDDomainOffset + sizeof(GrCacheID::Domain),
100 kResourceFlagsOffset = kResourceTypeOffset + sizeof(ResourceType), 85 kResourceFlagsOffset = kResourceTypeOffset + sizeof(ResourceType),
101 kPadOffset = kResourceFlagsOffset + sizeof(ResourceFlags), 86 kPadOffset = kResourceFlagsOffset + sizeof(ResourceFlags),
102 kKeySize = SkAlign4(kPadOffset), 87 kKeySize = SkAlign4(kPadOffset),
103 kPadSize = kKeySize - kPadOffset 88 kPadSize = kKeySize - kPadOffset
(...skipping 19 matching lines...) Expand all
123 GrBinHashKey<kKeySize> fKey; 108 GrBinHashKey<kKeySize> fKey;
124 }; 109 };
125 110
126 // The cache listens for these messages to purge junk resources proactively. 111 // The cache listens for these messages to purge junk resources proactively.
127 struct GrResourceInvalidatedMessage { 112 struct GrResourceInvalidatedMessage {
128 GrResourceKey key; 113 GrResourceKey key;
129 }; 114 };
130 115
131 /////////////////////////////////////////////////////////////////////////////// 116 ///////////////////////////////////////////////////////////////////////////////
132 117
118 /** GrResourceEntry represents one entry in lookup cache (hash). It might repres ent multiple entries
mtklein 2013/12/03 19:02:02 I think we need to rework this comment. /** GrRes
119 * (resources) in the GrResourceCache.
120 */
133 class GrResourceEntry { 121 class GrResourceEntry {
122 SK_DECLARE_NAMED_INTERNAL_LLIST(GrResource, CacheEntryResources, fResources) ;
123
134 public: 124 public:
135 GrResource* resource() const { return fResource; }
136 const GrResourceKey& key() const { return fKey; } 125 const GrResourceKey& key() const { return fKey; }
137 126
138 #ifdef SK_DEBUG 127 void addResource(GrResource* resource);
139 void validate() const; 128 /** Returns true if entry should be deleted. */
mtklein 2013/12/03 19:02:02 For consistency with the other methods below, it'd
140 #else 129 bool removeResource(GrResource* resource);
141 void validate() const {} 130 /** Returns true if entry should be deleted. */
142 #endif 131 bool removeExclusiveResource(GrResource* resource);
132
133 void makeExclusive(GrResource* resource);
134 void makeNonExclusive(GrResource* resource);
135
136 CacheEntryResourcesInternalLListType& resources() { return fResources; }
137
138 static const GrResourceKey& GetKey(const GrResourceEntry& e) { return e.key( ); }
139 static uint32_t GetKeyHash(const GrResourceKey& key) { return key.getHash(); }
140 static bool EqualsKey(const GrResourceEntry& a, const GrResourceKey& b) {
141 return a.key() == b;
142 }
143 143
144 private: 144 private:
145 GrResourceEntry(const GrResourceKey& key, GrResource* resource); 145 GrResourceEntry(const GrResourceKey& key, GrResource* firstResource);
146 ~GrResourceEntry(); 146 ~GrResourceEntry();
147 147
148 bool isEmpty() const { return fExclusiveCount == 0 && fResources.isEmpty(); }
149
148 GrResourceKey fKey; 150 GrResourceKey fKey;
149 GrResource* fResource; 151 int fExclusiveCount;
150
151 // we're a linked list
152 SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrResourceEntry);
153 152
154 friend class GrResourceCache; 153 friend class GrResourceCache;
155 friend class GrDLinkedList;
156 }; 154 };
157 155
158 inline bool GrResourceKey::LessThan(const GrResourceEntry& entry, const GrResour ceKey& key) {
159 return entry.key() < key;
160 }
161
162 inline bool GrResourceKey::Equals(const GrResourceEntry& entry, const GrResource Key& key) {
163 return entry.key() == key;
164 }
165
166 #ifdef SK_DEBUG
167 inline bool GrResourceKey::LessThan(const GrResourceEntry& a, const GrResourceEn try& b) {
168 return a.key() < b.key();
169 }
170
171 inline bool GrResourceKey::Equals(const GrResourceEntry& a, const GrResourceEntr y& b) {
172 return a.key() == b.key();
173 }
174 #endif
175
176 /////////////////////////////////////////////////////////////////////////////// 156 ///////////////////////////////////////////////////////////////////////////////
177 157
178 /** 158 /**
179 * Cache of GrResource objects. 159 * Cache of GrResource objects.
180 * 160 *
181 * These have a corresponding GrResourceKey, built from 128bits identifying the 161 * These have a corresponding GrResourceKey, built from 128bits identifying the
182 * resource. 162 * resource. Multiple resources can map to same GrResourceKey.
183 * 163 *
184 * The cache stores the entries in a double-linked list, which is its LRU. 164 * The cache stores the entries in a double-linked list, which is its LRU.
185 * When an entry is "locked" (i.e. given to the caller), it is moved to the 165 * When an entry is "locked" (i.e. given to the caller), it is moved to the
186 * head of the list. If/when we must purge some of the entries, we walk the 166 * head of the list. If/when we must purge some of the entries, we walk the
187 * list backwards from the tail, since those are the least recently used. 167 * list backwards from the tail, since those are the least recently used.
188 * 168 *
189 * For fast searches, we maintain a sorted array (based on the GrResourceKey) 169 * For fast searches, we maintain a hash map based on the GrResourceKey.
190 * which we can bsearch. When a new entry is added, it is inserted into this
191 * array.
192 *
193 * For even faster searches, a hash is computed from the Key. If there is
194 * a collision between two keys with the same hash, we fall back on the
195 * bsearch, and update the hash to reflect the most recent Key requested.
196 * 170 *
197 * It is a goal to make the GrResourceCache the central repository and bookkeep er 171 * It is a goal to make the GrResourceCache the central repository and bookkeep er
198 * of all resources. It should replace the linked list of GrResources that 172 * of all resources. It should replace the linked list of GrResources that
199 * GrGpu uses to call abandon/release. 173 * GrGpu uses to call abandon/release.
200 */ 174 */
201 class GrResourceCache { 175 class GrResourceCache {
202 public: 176 public:
203 GrResourceCache(int maxCount, size_t maxBytes); 177 GrResourceCache(int maxCount, size_t maxBytes);
204 ~GrResourceCache(); 178 ~GrResourceCache();
205 179
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 GrResource* resource, 258 GrResource* resource,
285 uint32_t ownershipFlags = 0); 259 uint32_t ownershipFlags = 0);
286 260
287 /** 261 /**
288 * Determines if the cache contains an entry matching a key. If a matching 262 * Determines if the cache contains an entry matching a key. If a matching
289 * entry exists but was detached then it will not be found. 263 * entry exists but was detached then it will not be found.
290 */ 264 */
291 bool hasKey(const GrResourceKey& key) const { return NULL != fCache.find(key ); } 265 bool hasKey(const GrResourceKey& key) const { return NULL != fCache.find(key ); }
292 266
293 /** 267 /**
294 * Hide 'entry' so that future searches will not find it. Such 268 * Hide 'resource' so that future searches will not find it. Such
295 * hidden entries will not be purged. The entry still counts against 269 * hidden resources will not be purged. The resource still counts against
296 * the cache's budget and should be made non-exclusive when exclusive access 270 * the cache's budget and should be made non-exclusive when exclusive access
297 * is no longer needed. 271 * is no longer needed.
298 */ 272 */
299 void makeExclusive(GrResourceEntry* entry); 273 void makeExclusive(GrResource* resource);
300 274
301 /** 275 /**
302 * Restore 'entry' so that it can be found by future searches. 'entry' 276 * Restore 'entry' so that it can be found by future searches. 'entry'
303 * will also be purgeable (provided its lock count is now 0.) 277 * will also be purgeable (provided its lock count is now 0.)
304 */ 278 */
305 void makeNonExclusive(GrResourceEntry* entry); 279 void makeNonExclusive(GrResource*);
mtklein 2013/12/03 19:02:02 I don't mind not naming parameters when it's obvio
306 280
307 /** 281 /**
308 * Remove a resource from the cache and delete it! 282 * Delete a resource from the cache.
309 */ 283 */
310 void deleteResource(GrResourceEntry* entry); 284 void deleteResource(GrResource* resource) {
285 SkASSERT(1 == resource->getRefCnt());
286 this->removeResource(resource);
287 }
311 288
312 /** 289 /**
313 * Removes every resource in the cache that isn't locked. 290 * Removes every resource in the cache that isn't locked.
314 */ 291 */
315 void purgeAllUnlocked(); 292 void purgeAllUnlocked();
316 293
317 /** 294 /**
318 * Allow cache to purge unused resources to obey resource limitations 295 * Allow cache to purge unused resources to obey resource limitations
319 * Note: this entry point will be hidden (again) once totally ref-driven 296 * Note: this entry point will be hidden (again) once totally ref-driven
320 * cache maintenance is implemented. Note that the overbudget callback 297 * cache maintenance is implemented. Note that the overbudget callback
(...skipping 15 matching lines...) Expand all
336 #if GR_CACHE_STATS 313 #if GR_CACHE_STATS
337 void printStats(); 314 void printStats();
338 #endif 315 #endif
339 316
340 private: 317 private:
341 enum BudgetBehaviors { 318 enum BudgetBehaviors {
342 kAccountFor_BudgetBehavior, 319 kAccountFor_BudgetBehavior,
343 kIgnore_BudgetBehavior 320 kIgnore_BudgetBehavior
344 }; 321 };
345 322
346 void internalDetach(GrResourceEntry*, BudgetBehaviors behavior = kAccountFor _BudgetBehavior); 323 /** Returns true if entry holding the resource is still valid. */
347 void attachToHead(GrResourceEntry*, BudgetBehaviors behavior = kAccountFor_B udgetBehavior); 324 bool removeResource(GrResource* resource);
348 325
349 void removeInvalidResource(GrResourceEntry* entry); 326 void internalDetach(GrResource*, BudgetBehaviors behavior = kAccountFor_Budg etBehavior);
327 void attachToHead(GrResource*, BudgetBehaviors behavior = kAccountFor_Budget Behavior);
350 328
351 GrTHashTable<GrResourceEntry, GrResourceKey, 8> fCache; 329 void removeInvalidResource(GrResource* resource);
352 330
353 // We're an internal doubly linked list 331 SkTDynamicHash<GrResourceEntry,
354 typedef SkTInternalLList<GrResourceEntry> EntryList; 332 GrResourceKey,
355 EntryList fList; 333 GrResourceEntry::GetKey,
334 GrResourceEntry::GetKeyHash,
335 GrResourceEntry::EqualsKey> fCache;
336
337 SK_DECLARE_NAMED_INTERNAL_LLIST(GrResource, CacheLRU, fList);
356 338
357 #ifdef SK_DEBUG 339 #ifdef SK_DEBUG
358 // These objects cannot be returned by a search 340 // These objects cannot be returned by a search
359 EntryList fExclusiveList; 341 CacheLRUInternalLListType fExclusiveList;
360 #endif 342 #endif
361 343
362 // our budget, used in purgeAsNeeded() 344 // our budget, used in purgeAsNeeded()
363 int fMaxCount; 345 int fMaxCount;
364 size_t fMaxBytes; 346 size_t fMaxBytes;
365 347
366 // our current stats, related to our budget 348 // our current stats, related to our budget
367 #if GR_CACHE_STATS 349 #if GR_CACHE_STATS
368 int fHighWaterEntryCount; 350 int fHighWaterEntryCount;
369 size_t fHighWaterEntryBytes; 351 size_t fHighWaterEntryBytes;
(...skipping 12 matching lines...) Expand all
382 PFOverbudgetCB fOverbudgetCB; 364 PFOverbudgetCB fOverbudgetCB;
383 void* fOverbudgetData; 365 void* fOverbudgetData;
384 366
385 void internalPurge(int extraCount, size_t extraBytes); 367 void internalPurge(int extraCount, size_t extraBytes);
386 368
387 // Listen for messages that a resource has been invalidated and purge cached junk proactively. 369 // Listen for messages that a resource has been invalidated and purge cached junk proactively.
388 SkMessageBus<GrResourceInvalidatedMessage>::Inbox fInvalidationInbox; 370 SkMessageBus<GrResourceInvalidatedMessage>::Inbox fInvalidationInbox;
389 void purgeInvalidated(); 371 void purgeInvalidated();
390 372
391 #ifdef SK_DEBUG 373 #ifdef SK_DEBUG
392 static size_t countBytes(const SkTInternalLList<GrResourceEntry>& list); 374 static size_t countBytes(const CacheLRUInternalLListType& list);
393 #endif 375 #endif
394 }; 376 };
395 377
396 /////////////////////////////////////////////////////////////////////////////// 378 ///////////////////////////////////////////////////////////////////////////////
397 379
398 #ifdef SK_DEBUG 380 #ifdef SK_DEBUG
399 class GrAutoResourceCacheValidate { 381 class GrAutoResourceCacheValidate {
400 public: 382 public:
401 GrAutoResourceCacheValidate(GrResourceCache* cache) : fCache(cache) { 383 GrAutoResourceCacheValidate(GrResourceCache* cache) : fCache(cache) {
402 cache->validate(); 384 cache->validate();
403 } 385 }
404 ~GrAutoResourceCacheValidate() { 386 ~GrAutoResourceCacheValidate() {
405 fCache->validate(); 387 fCache->validate();
406 } 388 }
407 private: 389 private:
408 GrResourceCache* fCache; 390 GrResourceCache* fCache;
409 }; 391 };
410 #else 392 #else
411 class GrAutoResourceCacheValidate { 393 class GrAutoResourceCacheValidate {
412 public: 394 public:
413 GrAutoResourceCacheValidate(GrResourceCache*) {} 395 GrAutoResourceCacheValidate(GrResourceCache*) {}
414 }; 396 };
415 #endif 397 #endif
416 398
417 #endif 399 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698