1 /* 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. 5 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. 10 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. 15 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. 20 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. 23 */ 24 25 #ifndef MemoryCache_h 26 #define MemoryCache_h 27 28 #include "core/fetch/Resource.h" 29 #include "core/fetch/ResourcePtr.h" 30 #include "public/platform/WebThread.h" 31 #include "wtf/HashMap.h" 32 #include "wtf/Noncopyable.h" 33 #include "wtf/Vector.h" 34 #include "wtf/text/StringHash.h" 35 #include "wtf/text/WTFString.h" 36 37 namespace WebCore { 38 39 class CSSStyleSheetResource; 40 class Resource; 41 class ResourceFetcher; 42 class KURL; 43 class ExecutionContext; 44 class SecurityOrigin; 45 struct SecurityOriginHash; 46 47 // This cache holds subresources used by Web pages: images, scripts, stylesheets, etc. 48 49 // The cache keeps a flexible but bounded window of dead resources that grows/shrinks 50 // depending on the live resource load. Here's an example of cache growth over time, 51 // with a min dead resource capacity of 25% and a max dead resource capacity of 50%: 52 53 // |-----| Dead: - 54 // |----------| Live: + 55 // --|----------| Cache boundary: | (objects outside this mark have been evicted) 56 // --|----------++++++++++| 57 // -------|-----+++++++++++++++| 58 // -------|-----+++++++++++++++|+++++ 59 60 // Enable this macro to periodically log information about the memory cache. 61 #undef MEMORY_CACHE_STATS 62 63 // Determines the order in which CachedResources are evicted 64 // from the decoded resources cache. 65 enum MemoryCacheLiveResourcePriority { 66 MemoryCacheLiveResourcePriorityLow = 0, 67 MemoryCacheLiveResourcePriorityHigh, 68 MemoryCacheLiveResourcePriorityUnknown 69 }; 70 71 enum UpdateReason { 72 UpdateForAccess, 73 UpdateForPropertyChange 74 }; 75 76 class MemoryCache FINAL : public blink::WebThread::TaskObserver { 77 WTF_MAKE_NONCOPYABLE(MemoryCache); WTF_MAKE_FAST_ALLOCATED; 78 public: 79 MemoryCache(); 80 virtual ~MemoryCache(); 81 82 class MemoryCacheEntry { 83 public: create(Resource * resource)84 static PassOwnPtr<MemoryCacheEntry> create(Resource* resource) { return adoptPtr(new MemoryCacheEntry(resource)); } 85 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 91 92 MemoryCacheEntry* m_previousInLiveResourcesList; 93 MemoryCacheEntry* m_nextInLiveResourcesList; 94 MemoryCacheEntry* m_previousInAllResourcesList; 95 MemoryCacheEntry* m_nextInAllResourcesList; 96 97 private: MemoryCacheEntry(Resource * resource)98 MemoryCacheEntry(Resource* resource) 99 : m_resource(resource) 100 , m_inLiveDecodedResourcesList(false) 101 , m_accessCount(0) 102 , m_liveResourcePriority(MemoryCacheLiveResourcePriorityLow) 103 , m_lastDecodedAccessTime(0.0) 104 , m_previousInLiveResourcesList(0) 105 , m_nextInLiveResourcesList(0) 106 , m_previousInAllResourcesList(0) 107 , m_nextInAllResourcesList(0) 108 { 109 } 110 }; 111 112 struct LRUList { 113 MemoryCacheEntry* m_head; 114 MemoryCacheEntry* m_tail; LRUListLRUList115 LRUList() : m_head(0), m_tail(0) { } 116 }; 117 118 struct TypeStatistic { 119 int count; 120 int size; 121 int liveSize; 122 int decodedSize; 123 int encodedSize; 124 int encodedSizeDuplicatedInDataURLs; 125 int purgeableSize; 126 int purgedSize; 127 TypeStatisticTypeStatistic128 TypeStatistic() 129 : count(0) 130 , size(0) 131 , liveSize(0) 132 , decodedSize(0) 133 , encodedSize(0) 134 , encodedSizeDuplicatedInDataURLs(0) 135 , purgeableSize(0) 136 , purgedSize(0) 137 { 138 } 139 140 void addResource(Resource*); 141 }; 142 143 struct Statistics { 144 TypeStatistic images; 145 TypeStatistic cssStyleSheets; 146 TypeStatistic scripts; 147 TypeStatistic xslStyleSheets; 148 TypeStatistic fonts; 149 TypeStatistic other; 150 }; 151 152 Resource* resourceForURL(const KURL&); 153 154 void add(Resource*); 155 void replace(Resource* newResource, Resource* oldResource); 156 void remove(Resource*); 157 bool contains(const Resource*) const; 158 159 static KURL removeFragmentIdentifierIfNeeded(const KURL& originalURL); 160 161 // Sets the cache's memory capacities, in bytes. These will hold only approximately, 162 // since the decoded cost of resources like scripts and stylesheets is not known. 163 // - minDeadBytes: The maximum number of bytes that dead resources should consume when the cache is under pressure. 164 // - maxDeadBytes: The maximum number of bytes that dead resources should consume when the cache is not under pressure. 165 // - totalBytes: The maximum number of bytes that the cache should consume overall. 166 void setCapacities(size_t minDeadBytes, size_t maxDeadBytes, size_t totalBytes); setDelayBeforeLiveDecodedPrune(double seconds)167 void setDelayBeforeLiveDecodedPrune(double seconds) { m_delayBeforeLiveDecodedPrune = seconds; } setMaxPruneDeferralDelay(double seconds)168 void setMaxPruneDeferralDelay(double seconds) { m_maxPruneDeferralDelay = seconds; } 169 170 void evictResources(); 171 172 void prune(Resource* justReleasedResource = 0); 173 174 // Called to adjust a resource's size, lru list position, and access count. 175 void update(Resource*, size_t oldSize, size_t newSize, bool wasAccessed = false); updateForAccess(Resource * resource)176 void updateForAccess(Resource* resource) { update(resource, resource->size(), resource->size(), true); } 177 void updateDecodedResource(Resource*, UpdateReason, MemoryCacheLiveResourcePriority = MemoryCacheLiveResourcePriorityUnknown); 178 179 void makeLive(Resource*); 180 void makeDead(Resource*); 181 182 static void removeURLFromCache(ExecutionContext*, const KURL&); 183 184 Statistics getStatistics(); 185 minDeadCapacity()186 size_t minDeadCapacity() const { return m_minDeadCapacity; } maxDeadCapacity()187 size_t maxDeadCapacity() const { return m_maxDeadCapacity; } capacity()188 size_t capacity() const { return m_capacity; } liveSize()189 size_t liveSize() const { return m_liveSize; } deadSize()190 size_t deadSize() const { return m_deadSize; } 191 192 // Exposed for testing 193 MemoryCacheLiveResourcePriority priority(Resource*) const; 194 195 // TaskObserver implementation 196 virtual void willProcessTask() OVERRIDE; 197 virtual void didProcessTask() OVERRIDE; 198 199 private: 200 LRUList* lruListFor(unsigned accessCount, size_t); 201 202 #ifdef MEMORY_CACHE_STATS 203 void dumpStats(Timer<MemoryCache>*); 204 void dumpLRULists(bool includeLive) const; 205 #endif 206 207 // Calls to put the cached resource into and out of LRU lists. 208 void insertInLRUList(MemoryCacheEntry*, LRUList*); 209 void removeFromLRUList(MemoryCacheEntry*, LRUList*); 210 211 // Track decoded resources that are in the cache and referenced by a Web page. 212 void insertInLiveDecodedResourcesList(MemoryCacheEntry*); 213 void removeFromLiveDecodedResourcesList(MemoryCacheEntry*); 214 215 size_t liveCapacity() const; 216 size_t deadCapacity() const; 217 218 // pruneDeadResources() - Flush decoded and encoded data from resources not referenced by Web pages. 219 // pruneLiveResources() - Flush decoded data from resources still referenced by Web pages. 220 void pruneDeadResources(); // Automatically decide how much to prune. 221 void pruneLiveResources(); 222 void pruneNow(double currentTime); 223 224 bool evict(MemoryCacheEntry*); 225 226 static void removeURLFromCacheInternal(ExecutionContext*, const KURL&); 227 228 bool m_inPruneResources; 229 bool m_prunePending; 230 double m_maxPruneDeferralDelay; 231 double m_pruneTimeStamp; 232 double m_pruneFrameTimeStamp; 233 234 size_t m_capacity; 235 size_t m_minDeadCapacity; 236 size_t m_maxDeadCapacity; 237 size_t m_maxDeferredPruneDeadCapacity; 238 double m_delayBeforeLiveDecodedPrune; 239 240 size_t m_liveSize; // The number of bytes currently consumed by "live" resources in the cache. 241 size_t m_deadSize; // The number of bytes currently consumed by "dead" resources in the cache. 242 243 // Size-adjusted and popularity-aware LRU list collection for cache objects. This collection can hold 244 // more resources than the cached resource map, since it can also hold "stale" multiple versions of objects that are 245 // waiting to die when the clients referencing them go away. 246 Vector<LRUList, 32> m_allResources; 247 248 // Lists just for live resources with decoded data. Access to this list is based off of painting the resource. 249 // The lists are ordered by decode priority, with higher indices having higher priorities. 250 LRUList m_liveDecodedResources[MemoryCacheLiveResourcePriorityHigh + 1]; 251 252 // A URL-based map of all resources that are in the cache (including the freshest version of objects that are currently being 253 // referenced by a Web page). 254 typedef HashMap<String, OwnPtr<MemoryCacheEntry> > ResourceMap; 255 ResourceMap m_resources; 256 257 friend class MemoryCacheTest; 258 #ifdef MEMORY_CACHE_STATS 259 Timer<MemoryCache> m_statsTimer; 260 #endif 261 }; 262 263 // Returns the global cache. 264 MemoryCache* memoryCache(); 265 266 // Sets the global cache, used to swap in a test instance. 267 void setMemoryCacheForTesting(MemoryCache*); 268 269 } 270 271 #endif 272