| OLD | NEW |
| 1 /* | 1 /* |
| 2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) | 2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) |
| 3 Copyright (C) 2001 Dirk Mueller <mueller@kde.org> | 3 Copyright (C) 2001 Dirk Mueller <mueller@kde.org> |
| 4 Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 4 Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
| 5 | 5 |
| 6 This library is free software; you can redistribute it and/or | 6 This library is free software; you can redistribute it and/or |
| 7 modify it under the terms of the GNU Library General Public | 7 modify it under the terms of the GNU Library General Public |
| 8 License as published by the Free Software Foundation; either | 8 License as published by the Free Software Foundation; either |
| 9 version 2 of the License, or (at your option) any later version. | 9 version 2 of the License, or (at your option) any later version. |
| 10 | 10 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 #include "public/platform/WebThread.h" | 33 #include "public/platform/WebThread.h" |
| 34 #include "wtf/Allocator.h" | 34 #include "wtf/Allocator.h" |
| 35 #include "wtf/HashMap.h" | 35 #include "wtf/HashMap.h" |
| 36 #include "wtf/Noncopyable.h" | 36 #include "wtf/Noncopyable.h" |
| 37 #include "wtf/Vector.h" | 37 #include "wtf/Vector.h" |
| 38 #include "wtf/text/StringHash.h" | 38 #include "wtf/text/StringHash.h" |
| 39 #include "wtf/text/WTFString.h" | 39 #include "wtf/text/WTFString.h" |
| 40 | 40 |
| 41 namespace blink { | 41 namespace blink { |
| 42 | 42 |
| 43 class Resource; | |
| 44 class KURL; | 43 class KURL; |
| 45 class ExecutionContext; | |
| 46 | 44 |
| 47 // This cache holds subresources used by Web pages: images, scripts, | 45 // Member<MemoryCacheEntry> + MemoryCacheEntry::clearResourceWeak() monitors |
| 48 // stylesheets, etc. | 46 // eviction from MemoryCache due to Resource garbage collection. |
| 49 | 47 // WeakMember<Resource> + Resource's prefinalizer cannot determine whether the |
| 50 // The cache keeps a flexible but bounded window of dead resources that | 48 // Resource was on MemoryCache or not, because WeakMember is already cleared |
| 51 // grows/shrinks depending on the live resource load. Here's an example of cache | 49 // when the prefinalizer is executed. |
| 52 // growth over time, with a min dead resource capacity of 25% and a max dead | |
| 53 // resource capacity of 50%: | |
| 54 // | |
| 55 // Dead: - | |
| 56 // Live: + | |
| 57 // Cache boundary: | (objects outside this mark have been evicted) | |
| 58 // | |
| 59 // |-----| | |
| 60 // |----------| | |
| 61 // --|----------| | |
| 62 // --|----------++++++++++| | |
| 63 // -------|-----+++++++++++++++| | |
| 64 // -------|-----+++++++++++++++|+++++ | |
| 65 | |
| 66 enum UpdateReason { UpdateForAccess, UpdateForPropertyChange }; | |
| 67 | |
| 68 // MemoryCacheEntry class is used only in MemoryCache class, but we don't make | |
| 69 // MemoryCacheEntry class an inner class of MemoryCache because of dependency | |
| 70 // from MemoryCacheLRUList. | |
| 71 class MemoryCacheEntry final : public GarbageCollected<MemoryCacheEntry> { | 50 class MemoryCacheEntry final : public GarbageCollected<MemoryCacheEntry> { |
| 72 public: | 51 public: |
| 73 static MemoryCacheEntry* create(Resource* resource) { | 52 static MemoryCacheEntry* create(Resource* resource) { |
| 74 return new MemoryCacheEntry(resource); | 53 return new MemoryCacheEntry(resource); |
| 75 } | 54 } |
| 76 DECLARE_TRACE(); | 55 DECLARE_TRACE(); |
| 77 void dispose(); | 56 Resource* resource() const { return m_resource; } |
| 78 Resource* resource(); | |
| 79 | 57 |
| 80 bool m_inLiveDecodedResourcesList; | |
| 81 unsigned m_accessCount; | |
| 82 double m_lastDecodedAccessTime; // Used as a thrash guard | 58 double m_lastDecodedAccessTime; // Used as a thrash guard |
| 83 | 59 |
| 84 Member<MemoryCacheEntry> m_previousInLiveResourcesList; | |
| 85 Member<MemoryCacheEntry> m_nextInLiveResourcesList; | |
| 86 Member<MemoryCacheEntry> m_previousInAllResourcesList; | |
| 87 Member<MemoryCacheEntry> m_nextInAllResourcesList; | |
| 88 | |
| 89 private: | 60 private: |
| 90 explicit MemoryCacheEntry(Resource* resource) | 61 explicit MemoryCacheEntry(Resource* resource) |
| 91 : m_inLiveDecodedResourcesList(false), | 62 : m_lastDecodedAccessTime(0.0), m_resource(resource) {} |
| 92 m_accessCount(0), | |
| 93 m_lastDecodedAccessTime(0.0), | |
| 94 m_previousInLiveResourcesList(nullptr), | |
| 95 m_nextInLiveResourcesList(nullptr), | |
| 96 m_previousInAllResourcesList(nullptr), | |
| 97 m_nextInAllResourcesList(nullptr), | |
| 98 m_resource(resource) {} | |
| 99 | 63 |
| 100 void clearResourceWeak(Visitor*); | 64 void clearResourceWeak(Visitor*); |
| 101 | 65 |
| 102 WeakMember<Resource> m_resource; | 66 WeakMember<Resource> m_resource; |
| 103 }; | 67 }; |
| 104 | 68 |
| 105 WILL_NOT_BE_EAGERLY_TRACED_CLASS(MemoryCacheEntry); | 69 WILL_NOT_BE_EAGERLY_TRACED_CLASS(MemoryCacheEntry); |
| 106 | 70 |
| 107 // MemoryCacheLRUList is used only in MemoryCache class, but we don't make | 71 // This cache holds subresources used by Web pages: images, scripts, |
| 108 // MemoryCacheLRUList an inner struct of MemoryCache because we can't define | 72 // stylesheets, etc. |
| 109 // VectorTraits for inner structs. | |
| 110 struct MemoryCacheLRUList final { | |
| 111 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | |
| 112 | |
| 113 public: | |
| 114 Member<MemoryCacheEntry> m_head; | |
| 115 Member<MemoryCacheEntry> m_tail; | |
| 116 | |
| 117 MemoryCacheLRUList() : m_head(nullptr), m_tail(nullptr) {} | |
| 118 DECLARE_TRACE(); | |
| 119 }; | |
| 120 | |
| 121 } // namespace blink | |
| 122 | |
| 123 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::MemoryCacheLRUList); | |
| 124 | |
| 125 namespace blink { | |
| 126 | |
| 127 class CORE_EXPORT MemoryCache final | 73 class CORE_EXPORT MemoryCache final |
| 128 : public GarbageCollectedFinalized<MemoryCache>, | 74 : public GarbageCollectedFinalized<MemoryCache>, |
| 129 public WebThread::TaskObserver, | 75 public WebThread::TaskObserver, |
| 130 public MemoryCacheDumpClient, | 76 public MemoryCacheDumpClient, |
| 131 public MemoryCoordinatorClient { | 77 public MemoryCoordinatorClient { |
| 132 USING_GARBAGE_COLLECTED_MIXIN(MemoryCache); | 78 USING_GARBAGE_COLLECTED_MIXIN(MemoryCache); |
| 133 WTF_MAKE_NONCOPYABLE(MemoryCache); | 79 WTF_MAKE_NONCOPYABLE(MemoryCache); |
| 134 | 80 |
| 135 public: | 81 public: |
| 136 static MemoryCache* create(); | 82 static MemoryCache* create(); |
| 137 ~MemoryCache(); | 83 ~MemoryCache(); |
| 138 DECLARE_TRACE(); | 84 DECLARE_TRACE(); |
| 139 | 85 |
| 140 struct TypeStatistic { | 86 struct TypeStatistic { |
| 141 STACK_ALLOCATED(); | 87 STACK_ALLOCATED(); |
| 142 size_t count; | 88 size_t count; |
| 143 size_t size; | 89 size_t size; |
| 144 size_t liveSize; | |
| 145 size_t decodedSize; | 90 size_t decodedSize; |
| 146 size_t encodedSize; | 91 size_t encodedSize; |
| 147 size_t overheadSize; | 92 size_t overheadSize; |
| 148 size_t encodedSizeDuplicatedInDataURLs; | 93 size_t encodedSizeDuplicatedInDataURLs; |
| 149 | 94 |
| 150 TypeStatistic() | 95 TypeStatistic() |
| 151 : count(0), | 96 : count(0), |
| 152 size(0), | 97 size(0), |
| 153 liveSize(0), | |
| 154 decodedSize(0), | 98 decodedSize(0), |
| 155 encodedSize(0), | 99 encodedSize(0), |
| 156 overheadSize(0), | 100 overheadSize(0), |
| 157 encodedSizeDuplicatedInDataURLs(0) {} | 101 encodedSizeDuplicatedInDataURLs(0) {} |
| 158 | 102 |
| 159 void addResource(Resource*); | 103 void addResource(Resource*); |
| 160 }; | 104 }; |
| 161 | 105 |
| 162 struct Statistics { | 106 struct Statistics { |
| 163 STACK_ALLOCATED(); | 107 STACK_ALLOCATED(); |
| 164 TypeStatistic images; | 108 TypeStatistic images; |
| 165 TypeStatistic cssStyleSheets; | 109 TypeStatistic cssStyleSheets; |
| 166 TypeStatistic scripts; | 110 TypeStatistic scripts; |
| 167 TypeStatistic xslStyleSheets; | 111 TypeStatistic xslStyleSheets; |
| 168 TypeStatistic fonts; | 112 TypeStatistic fonts; |
| 169 TypeStatistic other; | 113 TypeStatistic other; |
| 170 }; | 114 }; |
| 171 | 115 |
| 172 Resource* resourceForURL(const KURL&); | 116 Resource* resourceForURL(const KURL&) const; |
| 173 Resource* resourceForURL(const KURL&, const String& cacheIdentifier); | 117 Resource* resourceForURL(const KURL&, const String& cacheIdentifier) const; |
| 174 HeapVector<Member<Resource>> resourcesForURL(const KURL&); | 118 HeapVector<Member<Resource>> resourcesForURL(const KURL&) const; |
| 175 | 119 |
| 176 void add(Resource*); | 120 void add(Resource*); |
| 177 void remove(Resource*); | 121 void remove(Resource*); |
| 178 bool contains(const Resource*) const; | 122 bool contains(const Resource*) const; |
| 179 | 123 |
| 180 static KURL removeFragmentIdentifierIfNeeded(const KURL& originalURL); | 124 static KURL removeFragmentIdentifierIfNeeded(const KURL& originalURL); |
| 181 | 125 |
| 182 static String defaultCacheIdentifier(); | 126 static String defaultCacheIdentifier(); |
| 183 | 127 |
| 184 // Sets the cache's memory capacities, in bytes. These will hold only | 128 // Sets the cache's memory capacities, in bytes. These will hold only |
| 185 // approximately, since the decoded cost of resources like scripts and | 129 // approximately, since the decoded cost of resources like scripts and |
| 186 // stylesheets is not known. | 130 // stylesheets is not known. |
| 187 // - minDeadBytes: The maximum number of bytes that dead resources should | |
| 188 // consume when the cache is under pressure. | |
| 189 // - maxDeadBytes: The maximum number of bytes that dead resources should | |
| 190 // consume when the cache is not under pressure. | |
| 191 // - totalBytes: The maximum number of bytes that the cache should consume | 131 // - totalBytes: The maximum number of bytes that the cache should consume |
| 192 // overall. | 132 // overall. |
| 193 void setCapacities(size_t minDeadBytes, | 133 void setCapacity(size_t totalBytes); |
| 194 size_t maxDeadBytes, | |
| 195 size_t totalBytes); | |
| 196 void setDelayBeforeLiveDecodedPrune(double seconds) { | 134 void setDelayBeforeLiveDecodedPrune(double seconds) { |
| 197 m_delayBeforeLiveDecodedPrune = seconds; | 135 m_delayBeforeLiveDecodedPrune = seconds; |
| 198 } | 136 } |
| 199 void setMaxPruneDeferralDelay(double seconds) { | 137 void setMaxPruneDeferralDelay(double seconds) { |
| 200 m_maxPruneDeferralDelay = seconds; | 138 m_maxPruneDeferralDelay = seconds; |
| 201 } | 139 } |
| 202 | 140 |
| 203 enum EvictResourcePolicy { EvictAllResources, DoNotEvictUnusedPreloads }; | 141 enum EvictResourcePolicy { EvictAllResources, DoNotEvictUnusedPreloads }; |
| 204 void evictResources(EvictResourcePolicy = EvictAllResources); | 142 void evictResources(EvictResourcePolicy = EvictAllResources); |
| 205 | 143 |
| 206 void prune(); | 144 void prune(); |
| 207 | 145 |
| 208 // Called to adjust a resource's size, lru list position, and access count. | 146 // Called to update MemoryCache::size(). |
| 209 void update(Resource*, | 147 void update(Resource*, size_t oldSize, size_t newSize); |
| 210 size_t oldSize, | |
| 211 size_t newSize, | |
| 212 bool wasAccessed = false); | |
| 213 void updateForAccess(Resource* resource) { | |
| 214 update(resource, resource->size(), resource->size(), true); | |
| 215 } | |
| 216 void updateDecodedResource(Resource*, UpdateReason); | |
| 217 | |
| 218 void makeLive(Resource*); | |
| 219 void makeDead(Resource*); | |
| 220 | 148 |
| 221 void removeURLFromCache(const KURL&); | 149 void removeURLFromCache(const KURL&); |
| 222 | 150 |
| 223 Statistics getStatistics(); | 151 Statistics getStatistics() const; |
| 224 | 152 |
| 225 size_t minDeadCapacity() const { return m_minDeadCapacity; } | |
| 226 size_t maxDeadCapacity() const { return m_maxDeadCapacity; } | |
| 227 size_t capacity() const { return m_capacity; } | 153 size_t capacity() const { return m_capacity; } |
| 228 size_t liveSize() const { return m_liveSize; } | 154 size_t size() const { return m_size; } |
| 229 size_t deadSize() const { return m_deadSize; } | |
| 230 | 155 |
| 231 // TaskObserver implementation | 156 // TaskObserver implementation |
| 232 void willProcessTask() override; | 157 void willProcessTask() override; |
| 233 void didProcessTask() override; | 158 void didProcessTask() override; |
| 234 | 159 |
| 235 void pruneAll(); | 160 void pruneAll(); |
| 236 | 161 |
| 237 void updateFramePaintTimestamp(); | 162 void updateFramePaintTimestamp(); |
| 238 | 163 |
| 239 // Take memory usage snapshot for tracing. | 164 // Take memory usage snapshot for tracing. |
| 240 bool onMemoryDump(WebMemoryDumpLevelOfDetail, WebProcessMemoryDump*) override; | 165 bool onMemoryDump(WebMemoryDumpLevelOfDetail, WebProcessMemoryDump*) override; |
| 241 | 166 |
| 242 void onMemoryPressure(WebMemoryPressureLevel) override; | 167 void onMemoryPressure(WebMemoryPressureLevel) override; |
| 243 | 168 |
| 244 bool isInSameLRUListForTest(const Resource*, const Resource*); | |
| 245 | |
| 246 private: | 169 private: |
| 247 enum PruneStrategy { | 170 enum PruneStrategy { |
| 248 // Automatically decide how much to prune. | 171 // Automatically decide how much to prune. |
| 249 AutomaticPrune, | 172 AutomaticPrune, |
| 250 // Maximally prune resources. | 173 // Maximally prune resources. |
| 251 MaximalPrune | 174 MaximalPrune |
| 252 }; | 175 }; |
| 253 | 176 |
| 177 // A URL-based map of all resources that are in the cache (including the |
| 178 // freshest version of objects that are currently being referenced by a Web |
| 179 // page). removeFragmentIdentifierIfNeeded() should be called for the url |
| 180 // before using it as a key for the map. |
| 181 using ResourceMap = HeapHashMap<String, Member<MemoryCacheEntry>>; |
| 182 using ResourceMapIndex = HeapHashMap<String, Member<ResourceMap>>; |
| 183 ResourceMap* ensureResourceMap(const String& cacheIdentifier); |
| 184 ResourceMapIndex m_resourceMaps; |
| 185 |
| 254 MemoryCache(); | 186 MemoryCache(); |
| 255 | 187 |
| 256 MemoryCacheLRUList* lruListFor(unsigned accessCount, size_t); | 188 void addInternal(ResourceMap*, MemoryCacheEntry*); |
| 189 void removeInternal(ResourceMap*, const ResourceMap::iterator&); |
| 257 | 190 |
| 258 // Calls to put the cached resource into and out of LRU lists. | 191 void pruneResources(PruneStrategy); |
| 259 void insertInLRUList(MemoryCacheEntry*, MemoryCacheLRUList*); | |
| 260 void removeFromLRUList(MemoryCacheEntry*, MemoryCacheLRUList*); | |
| 261 bool containedInLRUList(MemoryCacheEntry*, MemoryCacheLRUList*); | |
| 262 | |
| 263 // Track decoded resources that are in the cache and referenced by a Web page. | |
| 264 void insertInLiveDecodedResourcesList(MemoryCacheEntry*); | |
| 265 void removeFromLiveDecodedResourcesList(MemoryCacheEntry*); | |
| 266 bool containedInLiveDecodedResourcesList(MemoryCacheEntry*); | |
| 267 | |
| 268 size_t liveCapacity() const; | |
| 269 size_t deadCapacity() const; | |
| 270 | |
| 271 // pruneDeadResources() - Flush decoded and encoded data from resources not | |
| 272 // referenced by Web pages. | |
| 273 // pruneLiveResources() - Flush decoded data from resources still referenced | |
| 274 // by Web pages. | |
| 275 void pruneDeadResources(PruneStrategy); | |
| 276 void pruneLiveResources(PruneStrategy); | |
| 277 void pruneNow(double currentTime, PruneStrategy); | 192 void pruneNow(double currentTime, PruneStrategy); |
| 278 | 193 |
| 279 void evict(MemoryCacheEntry*); | |
| 280 | |
| 281 MemoryCacheEntry* getEntryForResource(const Resource*) const; | |
| 282 | |
| 283 static void removeURLFromCacheInternal(ExecutionContext*, const KURL&); | |
| 284 | |
| 285 bool m_inPruneResources; | 194 bool m_inPruneResources; |
| 286 bool m_prunePending; | 195 bool m_prunePending; |
| 287 double m_maxPruneDeferralDelay; | 196 double m_maxPruneDeferralDelay; |
| 288 double m_pruneTimeStamp; | 197 double m_pruneTimeStamp; |
| 289 double m_pruneFrameTimeStamp; | 198 double m_pruneFrameTimeStamp; |
| 290 double m_lastFramePaintTimeStamp; // used for detecting decoded resource | 199 double m_lastFramePaintTimeStamp; // used for detecting decoded resource |
| 291 // thrash in the cache | 200 // thrash in the cache |
| 292 | 201 |
| 293 size_t m_capacity; | 202 size_t m_capacity; |
| 294 size_t m_minDeadCapacity; | |
| 295 size_t m_maxDeadCapacity; | |
| 296 size_t m_maxDeferredPruneDeadCapacity; | |
| 297 double m_delayBeforeLiveDecodedPrune; | 203 double m_delayBeforeLiveDecodedPrune; |
| 298 | 204 |
| 299 // The number of bytes currently consumed by "live" resources in the cache. | 205 // The number of bytes currently consumed by resources in the cache. |
| 300 size_t m_liveSize; | 206 size_t m_size; |
| 301 // The number of bytes currently consumed by "dead" resources in the cache. | |
| 302 size_t m_deadSize; | |
| 303 | |
| 304 // Size-adjusted and popularity-aware LRU list collection for cache objects. | |
| 305 // This collection can hold more resources than the cached resource map, since | |
| 306 // it can also hold "stale" multiple versions of objects that are waiting to | |
| 307 // die when the clients referencing them go away. | |
| 308 HeapVector<MemoryCacheLRUList, 32> m_allResources; | |
| 309 | |
| 310 // Lists just for live resources with decoded data. Access to this list is | |
| 311 // based off of painting the resource. | |
| 312 MemoryCacheLRUList m_liveDecodedResources; | |
| 313 | |
| 314 // A URL-based map of all resources that are in the cache (including the | |
| 315 // freshest version of objects that are currently being referenced by a Web | |
| 316 // page). removeFragmentIdentifierIfNeeded() should be called for the url | |
| 317 // before using it as a key for the map. | |
| 318 using ResourceMap = HeapHashMap<String, Member<MemoryCacheEntry>>; | |
| 319 using ResourceMapIndex = HeapHashMap<String, Member<ResourceMap>>; | |
| 320 ResourceMap* ensureResourceMap(const String& cacheIdentifier); | |
| 321 ResourceMapIndex m_resourceMaps; | |
| 322 | 207 |
| 323 friend class MemoryCacheTest; | 208 friend class MemoryCacheTest; |
| 324 }; | 209 }; |
| 325 | 210 |
| 326 // Returns the global cache. | 211 // Returns the global cache. |
| 327 CORE_EXPORT MemoryCache* memoryCache(); | 212 CORE_EXPORT MemoryCache* memoryCache(); |
| 328 | 213 |
| 329 // Sets the global cache, used to swap in a test instance. Returns the old | 214 // Sets the global cache, used to swap in a test instance. Returns the old |
| 330 // MemoryCache object. | 215 // MemoryCache object. |
| 331 CORE_EXPORT MemoryCache* replaceMemoryCacheForTesting(MemoryCache*); | 216 CORE_EXPORT MemoryCache* replaceMemoryCacheForTesting(MemoryCache*); |
| 332 | 217 |
| 333 } // namespace blink | 218 } // namespace blink |
| 334 | 219 |
| 335 #endif | 220 #endif |
| OLD | NEW |