1 /* 2 Copyright (C) 1998 Lars Knoll (knoll (at) mpi-hd.mpg.de) 3 Copyright (C) 2001 Dirk Mueller <mueller (at) 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 Cache_h 26 #define Cache_h 27 28 #include "CachePolicy.h" 29 #include "CachedResource.h" 30 #include "PlatformString.h" 31 #include <wtf/HashMap.h> 32 #include <wtf/HashSet.h> 33 #include <wtf/Noncopyable.h> 34 #include <wtf/Vector.h> 35 #include <wtf/text/StringHash.h> 36 37 namespace WebCore { 38 39 class CachedCSSStyleSheet; 40 class CachedResource; 41 class CachedResourceLoader; 42 class KURL; 43 class SecurityOrigin; 44 struct SecurityOriginHash; 45 46 // This cache holds subresources used by Web pages: images, scripts, stylesheets, etc. 47 48 // The cache keeps a flexible but bounded window of dead resources that grows/shrinks 49 // depending on the live resource load. Here's an example of cache growth over time, 50 // with a min dead resource capacity of 25% and a max dead resource capacity of 50%: 51 52 // |-----| Dead: - 53 // |----------| Live: + 54 // --|----------| Cache boundary: | (objects outside this mark have been evicted) 55 // --|----------++++++++++| 56 // -------|-----+++++++++++++++| 57 // -------|-----+++++++++++++++|+++++ 58 59 // The behavior of the cache changes in the following way if shouldMakeResourcePurgeableOnEviction 60 // returns true. 61 // 62 // 1. Dead resources in the cache are kept in non-purgeable memory. 63 // 2. When we prune dead resources, instead of freeing them, we mark their memory as purgeable and 64 // keep the resources until the kernel reclaims the purgeable memory. 65 // 66 // By leaving the in-cache dead resources in dirty resident memory, we decrease the likelihood of 67 // the kernel claiming that memory and forcing us to refetch the resource (for example when a user 68 // presses back). 69 // 70 // And by having an unbounded number of resource objects using purgeable memory, we can use as much 71 // memory as is available on the machine. The trade-off here is that the CachedResource object (and 72 // its member variables) are allocated in non-purgeable TC-malloc'd memory so we would see slightly 73 // more memory use due to this. 74 75 class MemoryCache { 76 WTF_MAKE_NONCOPYABLE(MemoryCache); WTF_MAKE_FAST_ALLOCATED; 77 public: 78 friend MemoryCache* memoryCache(); 79 80 typedef HashMap<String, CachedResource*> CachedResourceMap; 81 82 struct LRUList { 83 CachedResource* m_head; 84 CachedResource* m_tail; 85 LRUList() : m_head(0), m_tail(0) { } 86 }; 87 88 struct TypeStatistic { 89 int count; 90 int size; 91 int liveSize; 92 int decodedSize; 93 int purgeableSize; 94 int purgedSize; 95 TypeStatistic() : count(0), size(0), liveSize(0), decodedSize(0), purgeableSize(0), purgedSize(0) { } 96 void addResource(CachedResource*); 97 }; 98 99 struct Statistics { 100 TypeStatistic images; 101 TypeStatistic cssStyleSheets; 102 TypeStatistic scripts; 103 #if ENABLE(XSLT) 104 TypeStatistic xslStyleSheets; 105 #endif 106 TypeStatistic fonts; 107 }; 108 109 CachedResource* resourceForURL(const KURL&); 110 111 bool add(CachedResource* resource); 112 void remove(CachedResource* resource) { evict(resource); } 113 114 static KURL removeFragmentIdentifierIfNeeded(const KURL& originalURL); 115 116 void revalidationSucceeded(CachedResource* revalidatingResource, const ResourceResponse&); 117 void revalidationFailed(CachedResource* revalidatingResource); 118 119 // Sets the cache's memory capacities, in bytes. These will hold only approximately, 120 // since the decoded cost of resources like scripts and stylesheets is not known. 121 // - minDeadBytes: The maximum number of bytes that dead resources should consume when the cache is under pressure. 122 // - maxDeadBytes: The maximum number of bytes that dead resources should consume when the cache is not under pressure. 123 // - totalBytes: The maximum number of bytes that the cache should consume overall. 124 void setCapacities(unsigned minDeadBytes, unsigned maxDeadBytes, unsigned totalBytes); 125 126 // Turn the cache on and off. Disabling the cache will remove all resources from the cache. They may 127 // still live on if they are referenced by some Web page though. 128 void setDisabled(bool); 129 bool disabled() const { return m_disabled; } 130 131 void evictResources(); 132 133 void setPruneEnabled(bool enabled) { m_pruneEnabled = enabled; } 134 void prune() 135 { 136 if (m_liveSize + m_deadSize <= m_capacity && m_maxDeadCapacity && m_deadSize <= m_maxDeadCapacity) // Fast path. 137 return; 138 139 pruneDeadResources(); // Prune dead first, in case it was "borrowing" capacity from live. 140 pruneLiveResources(); 141 } 142 143 void setDeadDecodedDataDeletionInterval(double interval) { m_deadDecodedDataDeletionInterval = interval; } 144 double deadDecodedDataDeletionInterval() const { return m_deadDecodedDataDeletionInterval; } 145 146 void addCachedResourceLoader(CachedResourceLoader*); 147 void removeCachedResourceLoader(CachedResourceLoader*); 148 149 // Calls to put the cached resource into and out of LRU lists. 150 void insertInLRUList(CachedResource*); 151 void removeFromLRUList(CachedResource*); 152 153 // Called to adjust the cache totals when a resource changes size. 154 void adjustSize(bool live, int delta); 155 156 // Track decoded resources that are in the cache and referenced by a Web page. 157 void insertInLiveDecodedResourcesList(CachedResource*); 158 void removeFromLiveDecodedResourcesList(CachedResource*); 159 160 void addToLiveResourcesSize(CachedResource*); 161 void removeFromLiveResourcesSize(CachedResource*); 162 163 static bool shouldMakeResourcePurgeableOnEviction(); 164 165 // Function to collect cache statistics for the caches window in the Safari Debug menu. 166 Statistics getStatistics(); 167 168 void resourceAccessed(CachedResource*); 169 170 typedef HashSet<RefPtr<SecurityOrigin>, SecurityOriginHash> SecurityOriginSet; 171 void removeResourcesWithOrigin(SecurityOrigin*); 172 void getOriginsWithCache(SecurityOriginSet& origins); 173 174 #ifdef ANDROID_INSTRUMENT 175 unsigned getLiveSize() { return m_liveSize; } 176 unsigned getDeadSize() { return m_deadSize; } 177 #endif 178 179 180 private: 181 MemoryCache(); 182 ~MemoryCache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons. 183 184 LRUList* lruListFor(CachedResource*); 185 #ifndef NDEBUG 186 void dumpStats(); 187 void dumpLRULists(bool includeLive) const; 188 #endif 189 190 unsigned liveCapacity() const; 191 unsigned deadCapacity() const; 192 193 void pruneDeadResources(); // Flush decoded and encoded data from resources not referenced by Web pages. 194 void pruneLiveResources(); // Flush decoded data from resources still referenced by Web pages. 195 196 bool makeResourcePurgeable(CachedResource*); 197 void evict(CachedResource*); 198 199 bool m_disabled; // Whether or not the cache is enabled. 200 bool m_pruneEnabled; 201 bool m_inPruneDeadResources; 202 203 unsigned m_capacity; 204 unsigned m_minDeadCapacity; 205 unsigned m_maxDeadCapacity; 206 double m_deadDecodedDataDeletionInterval; 207 208 unsigned m_liveSize; // The number of bytes currently consumed by "live" resources in the cache. 209 unsigned m_deadSize; // The number of bytes currently consumed by "dead" resources in the cache. 210 211 // Size-adjusted and popularity-aware LRU list collection for cache objects. This collection can hold 212 // more resources than the cached resource map, since it can also hold "stale" multiple versions of objects that are 213 // waiting to die when the clients referencing them go away. 214 Vector<LRUList, 32> m_allResources; 215 216 // List just for live resources with decoded data. Access to this list is based off of painting the resource. 217 LRUList m_liveDecodedResources; 218 219 // A URL-based map of all resources that are in the cache (including the freshest version of objects that are currently being 220 // referenced by a Web page). 221 HashMap<String, CachedResource*> m_resources; 222 }; 223 224 inline bool MemoryCache::shouldMakeResourcePurgeableOnEviction() 225 { 226 #if PLATFORM(IOS) 227 return true; 228 #else 229 return false; 230 #endif 231 } 232 233 // Function to obtain the global cache. 234 MemoryCache* memoryCache(); 235 236 } 237 238 #endif 239