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 |