Home | History | Annotate | Download | only in cache
      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