2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
3 Copyright (C) 2001 Dirk Mueller <mueller@kde.org>
4 Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
21 This class provides all functionality needed for loading images, style sheets and html
22 pages from the web. It has a memory cache for these objects.
28 #include "core/CoreExport.h"
29 #include "core/fetch/Resource.h"
30 #include "core/fetch/ResourcePtr.h"
31 #include "public/platform/WebThread.h"
32 #include "wtf/Allocator.h"
33 #include "wtf/HashMap.h"
34 #include "wtf/Noncopyable.h"
35 #include "wtf/Vector.h"
36 #include "wtf/text/StringHash.h"
37 #include "wtf/text/WTFString.h"
43 class ExecutionContext
;
45 // This cache holds subresources used by Web pages: images, scripts, stylesheets, etc.
47 // The cache keeps a flexible but bounded window of dead resources that grows/shrinks
48 // depending on the live resource load. Here's an example of cache growth over time,
49 // with a min dead resource capacity of 25% and a max dead resource capacity of 50%:
52 // |----------| Live: +
53 // --|----------| Cache boundary: | (objects outside this mark have been evicted)
54 // --|----------++++++++++|
55 // -------|-----+++++++++++++++|
56 // -------|-----+++++++++++++++|+++++
58 // Enable this macro to periodically log information about the memory cache.
59 #undef MEMORY_CACHE_STATS
61 // Determines the order in which CachedResources are evicted
62 // from the decoded resources cache.
63 enum MemoryCacheLiveResourcePriority
{
64 MemoryCacheLiveResourcePriorityLow
= 0,
65 MemoryCacheLiveResourcePriorityHigh
,
66 MemoryCacheLiveResourcePriorityUnknown
71 UpdateForPropertyChange
74 // MemoryCacheEntry class is used only in MemoryCache class, but we don't make
75 // MemoryCacheEntry class an inner class of MemoryCache because of dependency
76 // from MemoryCacheLRUList.
77 class MemoryCacheEntry final
: public GarbageCollectedFinalized
<MemoryCacheEntry
> {
79 static MemoryCacheEntry
* create(Resource
* resource
)
81 return new MemoryCacheEntry(resource
);
86 ResourcePtr
<Resource
> m_resource
;
87 bool m_inLiveDecodedResourcesList
;
88 unsigned m_accessCount
;
89 MemoryCacheLiveResourcePriority m_liveResourcePriority
;
90 double m_lastDecodedAccessTime
; // Used as a thrash guard
92 Member
<MemoryCacheEntry
> m_previousInLiveResourcesList
;
93 Member
<MemoryCacheEntry
> m_nextInLiveResourcesList
;
94 Member
<MemoryCacheEntry
> m_previousInAllResourcesList
;
95 Member
<MemoryCacheEntry
> m_nextInAllResourcesList
;
98 explicit MemoryCacheEntry(Resource
* resource
)
99 : m_resource(resource
)
100 , m_inLiveDecodedResourcesList(false)
102 , m_liveResourcePriority(MemoryCacheLiveResourcePriorityLow
)
103 , m_lastDecodedAccessTime(0.0)
104 , m_previousInLiveResourcesList(nullptr)
105 , m_nextInLiveResourcesList(nullptr)
106 , m_previousInAllResourcesList(nullptr)
107 , m_nextInAllResourcesList(nullptr)
112 WILL_NOT_BE_EAGERLY_TRACED_CLASS(MemoryCacheEntry
);
114 // MemoryCacheLRUList is used only in MemoryCache class, but we don't make
115 // MemoryCacheLRUList an inner struct of MemoryCache because we can't define
116 // VectorTraits for inner structs.
117 struct MemoryCacheLRUList final
{
118 ALLOW_ONLY_INLINE_ALLOCATION();
120 Member
<MemoryCacheEntry
> m_head
;
121 Member
<MemoryCacheEntry
> m_tail
;
123 MemoryCacheLRUList() : m_head(nullptr), m_tail(nullptr) { }
129 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::MemoryCacheLRUList
);
133 class CORE_EXPORT MemoryCache final
: public GarbageCollectedFinalized
<MemoryCache
>, public WebThread::TaskObserver
{
134 WTF_MAKE_NONCOPYABLE(MemoryCache
);
136 static MemoryCache
* create();
140 struct TypeStatistic
{
147 size_t encodedSizeDuplicatedInDataURLs
;
148 size_t purgeableSize
;
157 , encodedSizeDuplicatedInDataURLs(0)
163 void addResource(Resource
*);
168 TypeStatistic images
;
169 TypeStatistic cssStyleSheets
;
170 TypeStatistic scripts
;
171 TypeStatistic xslStyleSheets
;
176 Resource
* resourceForURL(const KURL
&);
177 Resource
* resourceForURL(const KURL
&, const String
& cacheIdentifier
);
178 WillBeHeapVector
<RawPtrWillBeMember
<Resource
>> resourcesForURL(const KURL
&);
181 void replace(Resource
* newResource
, Resource
* oldResource
);
182 void remove(Resource
*);
183 bool contains(const Resource
*) const;
185 static KURL
removeFragmentIdentifierIfNeeded(const KURL
& originalURL
);
187 static String
defaultCacheIdentifier();
189 // Sets the cache's memory capacities, in bytes. These will hold only approximately,
190 // since the decoded cost of resources like scripts and stylesheets is not known.
191 // - minDeadBytes: The maximum number of bytes that dead resources should consume when the cache is under pressure.
192 // - maxDeadBytes: The maximum number of bytes that dead resources should consume when the cache is not under pressure.
193 // - totalBytes: The maximum number of bytes that the cache should consume overall.
194 void setCapacities(size_t minDeadBytes
, size_t maxDeadBytes
, size_t totalBytes
);
195 void setDelayBeforeLiveDecodedPrune(double seconds
) { m_delayBeforeLiveDecodedPrune
= seconds
; }
196 void setMaxPruneDeferralDelay(double seconds
) { m_maxPruneDeferralDelay
= seconds
; }
198 void evictResources();
200 void prune(Resource
* justReleasedResource
= 0);
202 // Called to adjust a resource's size, lru list position, and access count.
203 void update(Resource
*, size_t oldSize
, size_t newSize
, bool wasAccessed
= false);
204 void updateForAccess(Resource
* resource
) { update(resource
, resource
->size(), resource
->size(), true); }
205 void updateDecodedResource(Resource
*, UpdateReason
, MemoryCacheLiveResourcePriority
= MemoryCacheLiveResourcePriorityUnknown
);
207 void makeLive(Resource
*);
208 void makeDead(Resource
*);
210 // This should be called when a Resource object is created.
211 void registerLiveResource(Resource
&);
212 // This should be called when a Resource object becomes unnecesarry.
213 void unregisterLiveResource(Resource
&);
215 void removeURLFromCache(const KURL
&);
217 Statistics
getStatistics();
219 size_t minDeadCapacity() const { return m_minDeadCapacity
; }
220 size_t maxDeadCapacity() const { return m_maxDeadCapacity
; }
221 size_t capacity() const { return m_capacity
; }
222 size_t liveSize() const { return m_liveSize
; }
223 size_t deadSize() const { return m_deadSize
; }
225 // Exposed for testing
226 MemoryCacheLiveResourcePriority
priority(Resource
*) const;
228 // TaskObserver implementation
229 void willProcessTask() override
;
230 void didProcessTask() override
;
234 void updateFramePaintTimestamp();
238 // Automatically decide how much to prune.
240 // Maximally prune resources.
246 MemoryCacheLRUList
* lruListFor(unsigned accessCount
, size_t);
248 #ifdef MEMORY_CACHE_STATS
249 void dumpStats(Timer
<MemoryCache
>*);
250 void dumpLRULists(bool includeLive
) const;
253 // Calls to put the cached resource into and out of LRU lists.
254 void insertInLRUList(MemoryCacheEntry
*, MemoryCacheLRUList
*);
255 void removeFromLRUList(MemoryCacheEntry
*, MemoryCacheLRUList
*);
256 bool containedInLRUList(MemoryCacheEntry
*, MemoryCacheLRUList
*);
258 // Track decoded resources that are in the cache and referenced by a Web page.
259 void insertInLiveDecodedResourcesList(MemoryCacheEntry
*);
260 void removeFromLiveDecodedResourcesList(MemoryCacheEntry
*);
261 bool containedInLiveDecodedResourcesList(MemoryCacheEntry
*);
263 size_t liveCapacity() const;
264 size_t deadCapacity() const;
266 // pruneDeadResources() - Flush decoded and encoded data from resources not referenced by Web pages.
267 // pruneLiveResources() - Flush decoded data from resources still referenced by Web pages.
268 void pruneDeadResources(PruneStrategy
);
269 void pruneLiveResources(PruneStrategy
);
270 void pruneNow(double currentTime
, PruneStrategy
);
272 bool evict(MemoryCacheEntry
*);
274 MemoryCacheEntry
* getEntryForResource(const Resource
*) const;
276 static void removeURLFromCacheInternal(ExecutionContext
*, const KURL
&);
278 bool m_inPruneResources
;
280 double m_maxPruneDeferralDelay
;
281 double m_pruneTimeStamp
;
282 double m_pruneFrameTimeStamp
;
283 double m_lastFramePaintTimeStamp
; // used for detecting decoded resource thrash in the cache
286 size_t m_minDeadCapacity
;
287 size_t m_maxDeadCapacity
;
288 size_t m_maxDeferredPruneDeadCapacity
;
289 double m_delayBeforeLiveDecodedPrune
;
291 size_t m_liveSize
; // The number of bytes currently consumed by "live" resources in the cache.
292 size_t m_deadSize
; // The number of bytes currently consumed by "dead" resources in the cache.
294 // Size-adjusted and popularity-aware LRU list collection for cache objects. This collection can hold
295 // more resources than the cached resource map, since it can also hold "stale" multiple versions of objects that are
296 // waiting to die when the clients referencing them go away.
297 HeapVector
<MemoryCacheLRUList
, 32> m_allResources
;
299 // Lists just for live resources with decoded data. Access to this list is based off of painting the resource.
300 // The lists are ordered by decode priority, with higher indices having higher priorities.
301 MemoryCacheLRUList m_liveDecodedResources
[MemoryCacheLiveResourcePriorityHigh
+ 1];
303 // A URL-based map of all resources that are in the cache (including the freshest version of objects that are currently being
304 // referenced by a Web page).
305 using ResourceMap
= HeapHashMap
<String
, Member
<MemoryCacheEntry
>>;
306 using ResourceMapIndex
= HeapHashMap
<String
, Member
<ResourceMap
>>;
307 ResourceMap
* ensureResourceMap(const String
& cacheIdentifier
);
308 ResourceMapIndex m_resourceMaps
;
311 // Unlike m_allResources, m_liveResources is a set of Resource objects which
312 // should not be deleted. m_allResources only contains on-cache Resource
314 // FIXME: Can we remove manual lifetime management of Resource and this?
315 HeapHashSet
<Member
<Resource
>> m_liveResources
;
316 friend CORE_EXPORT MemoryCache
* replaceMemoryCacheForTesting(MemoryCache
*);
319 friend class MemoryCacheTest
;
320 #ifdef MEMORY_CACHE_STATS
321 Timer
<MemoryCache
> m_statsTimer
;
325 // Returns the global cache.
326 CORE_EXPORT MemoryCache
* memoryCache();
328 // Sets the global cache, used to swap in a test instance. Returns the old
329 // MemoryCache object.
330 CORE_EXPORT MemoryCache
* replaceMemoryCacheForTesting(MemoryCache
*);