| OLD | NEW |
| (Empty) |
| 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 sheet
s and html | |
| 22 pages from the web. It has a memory cache for these objects. | |
| 23 */ | |
| 24 | |
| 25 #ifndef SKY_ENGINE_CORE_FETCH_MEMORYCACHE_H_ | |
| 26 #define SKY_ENGINE_CORE_FETCH_MEMORYCACHE_H_ | |
| 27 | |
| 28 #include "base/cancelable_callback.h" | |
| 29 #include "sky/engine/core/fetch/Resource.h" | |
| 30 #include "sky/engine/core/fetch/ResourcePtr.h" | |
| 31 #include "sky/engine/public/platform/WebThread.h" | |
| 32 #include "sky/engine/wtf/HashMap.h" | |
| 33 #include "sky/engine/wtf/Noncopyable.h" | |
| 34 #include "sky/engine/wtf/Vector.h" | |
| 35 #include "sky/engine/wtf/text/StringHash.h" | |
| 36 #include "sky/engine/wtf/text/WTFString.h" | |
| 37 | |
| 38 namespace blink { | |
| 39 | |
| 40 class Resource; | |
| 41 class ResourceFetcher; | |
| 42 class KURL; | |
| 43 class ExecutionContext; | |
| 44 | |
| 45 // This cache holds subresources used by Web pages: images, scripts, stylesheets
, etc. | |
| 46 | |
| 47 // The cache keeps a flexible but bounded window of dead resources that grows/sh
rinks | |
| 48 // depending on the live resource load. Here's an example of cache growth over t
ime, | |
| 49 // with a min dead resource capacity of 25% and a max dead resource capacity of
50%: | |
| 50 | |
| 51 // |-----| Dead: - | |
| 52 // |----------| Live: + | |
| 53 // --|----------| Cache boundary: | (objects outsid
e this mark have been evicted) | |
| 54 // --|----------++++++++++| | |
| 55 // -------|-----+++++++++++++++| | |
| 56 // -------|-----+++++++++++++++|+++++ | |
| 57 | |
| 58 // Enable this macro to periodically log information about the memory cache. | |
| 59 #undef MEMORY_CACHE_STATS | |
| 60 | |
| 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 | |
| 67 }; | |
| 68 | |
| 69 enum UpdateReason { | |
| 70 UpdateForAccess, | |
| 71 UpdateForPropertyChange | |
| 72 }; | |
| 73 | |
| 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 { | |
| 78 public: | |
| 79 static PassOwnPtr<MemoryCacheEntry> create(Resource* resource) { return adop
tPtr(new MemoryCacheEntry(resource)); } | |
| 80 | |
| 81 ResourcePtr<Resource> m_resource; | |
| 82 bool m_inLiveDecodedResourcesList; | |
| 83 unsigned m_accessCount; | |
| 84 MemoryCacheLiveResourcePriority m_liveResourcePriority; | |
| 85 double m_lastDecodedAccessTime; // Used as a thrash guard | |
| 86 | |
| 87 RawPtr<MemoryCacheEntry> m_previousInLiveResourcesList; | |
| 88 RawPtr<MemoryCacheEntry> m_nextInLiveResourcesList; | |
| 89 RawPtr<MemoryCacheEntry> m_previousInAllResourcesList; | |
| 90 RawPtr<MemoryCacheEntry> m_nextInAllResourcesList; | |
| 91 | |
| 92 private: | |
| 93 explicit MemoryCacheEntry(Resource* resource) | |
| 94 : m_resource(resource) | |
| 95 , m_inLiveDecodedResourcesList(false) | |
| 96 , m_accessCount(0) | |
| 97 , m_liveResourcePriority(MemoryCacheLiveResourcePriorityLow) | |
| 98 , m_lastDecodedAccessTime(0.0) | |
| 99 , m_previousInLiveResourcesList(nullptr) | |
| 100 , m_nextInLiveResourcesList(nullptr) | |
| 101 , m_previousInAllResourcesList(nullptr) | |
| 102 , m_nextInAllResourcesList(nullptr) | |
| 103 { | |
| 104 } | |
| 105 }; | |
| 106 | |
| 107 // MemoryCacheLRUList is used only in MemoryCache class, but we don't make | |
| 108 // MemoryCacheLRUList an inner struct of MemoryCache because we can't define | |
| 109 // VectorTraits for inner structs. | |
| 110 struct MemoryCacheLRUList final { | |
| 111 ALLOW_ONLY_INLINE_ALLOCATION(); | |
| 112 public: | |
| 113 RawPtr<MemoryCacheEntry> m_head; | |
| 114 RawPtr<MemoryCacheEntry> m_tail; | |
| 115 | |
| 116 MemoryCacheLRUList() : m_head(nullptr), m_tail(nullptr) { } | |
| 117 }; | |
| 118 | |
| 119 } | |
| 120 | |
| 121 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::MemoryCacheLRUList); | |
| 122 | |
| 123 namespace blink { | |
| 124 | |
| 125 class MemoryCache final { | |
| 126 WTF_MAKE_NONCOPYABLE(MemoryCache); WTF_MAKE_FAST_ALLOCATED; | |
| 127 public: | |
| 128 static PassOwnPtr<MemoryCache> create(); | |
| 129 ~MemoryCache(); | |
| 130 | |
| 131 struct TypeStatistic { | |
| 132 int count; | |
| 133 int size; | |
| 134 int liveSize; | |
| 135 int decodedSize; | |
| 136 int encodedSize; | |
| 137 int encodedSizeDuplicatedInDataURLs; | |
| 138 int purgeableSize; | |
| 139 int purgedSize; | |
| 140 | |
| 141 TypeStatistic() | |
| 142 : count(0) | |
| 143 , size(0) | |
| 144 , liveSize(0) | |
| 145 , decodedSize(0) | |
| 146 , encodedSize(0) | |
| 147 , encodedSizeDuplicatedInDataURLs(0) | |
| 148 , purgeableSize(0) | |
| 149 , purgedSize(0) | |
| 150 { | |
| 151 } | |
| 152 | |
| 153 void addResource(Resource*); | |
| 154 }; | |
| 155 | |
| 156 struct Statistics { | |
| 157 TypeStatistic images; | |
| 158 TypeStatistic cssStyleSheets; | |
| 159 TypeStatistic scripts; | |
| 160 TypeStatistic xslStyleSheets; | |
| 161 TypeStatistic fonts; | |
| 162 TypeStatistic other; | |
| 163 }; | |
| 164 | |
| 165 Resource* resourceForURL(const KURL&); | |
| 166 | |
| 167 void add(Resource*); | |
| 168 void replace(Resource* newResource, Resource* oldResource); | |
| 169 void remove(Resource*); | |
| 170 bool contains(const Resource*) const; | |
| 171 | |
| 172 static KURL removeFragmentIdentifierIfNeeded(const KURL& originalURL); | |
| 173 | |
| 174 // Sets the cache's memory capacities, in bytes. These will hold only approx
imately, | |
| 175 // since the decoded cost of resources like scripts and stylesheets is not k
nown. | |
| 176 // - minDeadBytes: The maximum number of bytes that dead resources should c
onsume when the cache is under pressure. | |
| 177 // - maxDeadBytes: The maximum number of bytes that dead resources should c
onsume when the cache is not under pressure. | |
| 178 // - totalBytes: The maximum number of bytes that the cache should consume
overall. | |
| 179 void setCapacities(size_t minDeadBytes, size_t maxDeadBytes, size_t totalByt
es); | |
| 180 void setDelayBeforeLiveDecodedPrune(double seconds) { m_delayBeforeLiveDecod
edPrune = seconds; } | |
| 181 void setMaxPruneDeferralDelay(double seconds) { m_maxPruneDeferralDelay = se
conds; } | |
| 182 | |
| 183 void evictResources(); | |
| 184 | |
| 185 void prune(Resource* justReleasedResource = 0); | |
| 186 | |
| 187 // Called to adjust a resource's size, lru list position, and access count. | |
| 188 void update(Resource*, size_t oldSize, size_t newSize, bool wasAccessed = fa
lse); | |
| 189 void updateForAccess(Resource* resource) { update(resource, resource->size()
, resource->size(), true); } | |
| 190 void updateDecodedResource(Resource*, UpdateReason, MemoryCacheLiveResourceP
riority = MemoryCacheLiveResourcePriorityUnknown); | |
| 191 | |
| 192 void makeLive(Resource*); | |
| 193 void makeDead(Resource*); | |
| 194 | |
| 195 // This should be called when a Resource object is created. | |
| 196 void registerLiveResource(Resource&); | |
| 197 // This should be called when a Resource object becomes unnecesarry. | |
| 198 void unregisterLiveResource(Resource&); | |
| 199 | |
| 200 static void removeURLFromCache(ExecutionContext*, const KURL&); | |
| 201 | |
| 202 Statistics getStatistics(); | |
| 203 | |
| 204 size_t minDeadCapacity() const { return m_minDeadCapacity; } | |
| 205 size_t maxDeadCapacity() const { return m_maxDeadCapacity; } | |
| 206 size_t capacity() const { return m_capacity; } | |
| 207 size_t liveSize() const { return m_liveSize; } | |
| 208 size_t deadSize() const { return m_deadSize; } | |
| 209 | |
| 210 // Exposed for testing | |
| 211 MemoryCacheLiveResourcePriority priority(Resource*) const; | |
| 212 | |
| 213 private: | |
| 214 MemoryCache(); | |
| 215 | |
| 216 MemoryCacheLRUList* lruListFor(unsigned accessCount, size_t); | |
| 217 | |
| 218 #ifdef MEMORY_CACHE_STATS | |
| 219 void dumpStats(Timer<MemoryCache>*); | |
| 220 void dumpLRULists(bool includeLive) const; | |
| 221 #endif | |
| 222 | |
| 223 // Calls to put the cached resource into and out of LRU lists. | |
| 224 void insertInLRUList(MemoryCacheEntry*, MemoryCacheLRUList*); | |
| 225 void removeFromLRUList(MemoryCacheEntry*, MemoryCacheLRUList*); | |
| 226 | |
| 227 // Track decoded resources that are in the cache and referenced by a Web pag
e. | |
| 228 void insertInLiveDecodedResourcesList(MemoryCacheEntry*); | |
| 229 void removeFromLiveDecodedResourcesList(MemoryCacheEntry*); | |
| 230 | |
| 231 size_t liveCapacity() const; | |
| 232 size_t deadCapacity() const; | |
| 233 | |
| 234 void pruneMicrotask(); | |
| 235 // pruneDeadResources() - Flush decoded and encoded data from resources not
referenced by Web pages. | |
| 236 // pruneLiveResources() - Flush decoded data from resources still referenced
by Web pages. | |
| 237 void pruneDeadResources(); // Automatically decide how much to prune. | |
| 238 void pruneLiveResources(); | |
| 239 void pruneNow(double currentTime); | |
| 240 | |
| 241 bool evict(MemoryCacheEntry*); | |
| 242 | |
| 243 bool prunePending() const { return !m_pendingPrune.IsCancelled(); } | |
| 244 | |
| 245 static void removeURLFromCacheInternal(ExecutionContext*, const KURL&); | |
| 246 | |
| 247 bool m_inPruneResources; | |
| 248 double m_maxPruneDeferralDelay; | |
| 249 double m_pruneTimeStamp; | |
| 250 double m_pruneFrameTimeStamp; | |
| 251 | |
| 252 size_t m_capacity; | |
| 253 size_t m_minDeadCapacity; | |
| 254 size_t m_maxDeadCapacity; | |
| 255 size_t m_maxDeferredPruneDeadCapacity; | |
| 256 double m_delayBeforeLiveDecodedPrune; | |
| 257 | |
| 258 size_t m_liveSize; // The number of bytes currently consumed by "live" resou
rces in the cache. | |
| 259 size_t m_deadSize; // The number of bytes currently consumed by "dead" resou
rces in the cache. | |
| 260 | |
| 261 base::CancelableClosure m_pendingPrune; | |
| 262 | |
| 263 // Size-adjusted and popularity-aware LRU list collection for cache objects.
This collection can hold | |
| 264 // more resources than the cached resource map, since it can also hold "stal
e" multiple versions of objects that are | |
| 265 // waiting to die when the clients referencing them go away. | |
| 266 Vector<MemoryCacheLRUList, 32> m_allResources; | |
| 267 | |
| 268 // Lists just for live resources with decoded data. Access to this list is b
ased off of painting the resource. | |
| 269 // The lists are ordered by decode priority, with higher indices having high
er priorities. | |
| 270 MemoryCacheLRUList m_liveDecodedResources[MemoryCacheLiveResourcePriorityHig
h + 1]; | |
| 271 | |
| 272 // A URL-based map of all resources that are in the cache (including the fre
shest version of objects that are currently being | |
| 273 // referenced by a Web page). | |
| 274 typedef HashMap<String, OwnPtr<MemoryCacheEntry> > ResourceMap; | |
| 275 ResourceMap m_resources; | |
| 276 | |
| 277 friend class MemoryCacheTest; | |
| 278 #ifdef MEMORY_CACHE_STATS | |
| 279 Timer<MemoryCache> m_statsTimer; | |
| 280 #endif | |
| 281 }; | |
| 282 | |
| 283 // Returns the global cache. | |
| 284 MemoryCache* memoryCache(); | |
| 285 | |
| 286 // Sets the global cache, used to swap in a test instance. Returns the old | |
| 287 // MemoryCache object. | |
| 288 PassOwnPtr<MemoryCache> replaceMemoryCacheForTesting(PassOwnPtr<MemoryCache>); | |
| 289 | |
| 290 } | |
| 291 | |
| 292 #endif // SKY_ENGINE_CORE_FETCH_MEMORYCACHE_H_ | |
| OLD | NEW |