Title: [179052] trunk/Source/WebKit2
Revision
179052
Author
[email protected]
Date
2015-01-23 18:27:31 -0800 (Fri, 23 Jan 2015)

Log Message

Implement cache size limit
https://bugs.webkit.org/show_bug.cgi?id=140844

Reviewed by Andreas Kling.

Prevent the cache from growing without bounds. The simple scheme implemented here
estimates the cache size from number of entries. When the estimated size exceeds
the maximum size we randomly clear 1/4 of the entries.

* NetworkProcess/cache/NetworkCacheStorage.h:
* NetworkProcess/cache/NetworkCacheStorageCocoa.mm:
(WebKit::NetworkCacheStorage::NetworkCacheStorage):
(WebKit::NetworkCacheStorage::initialize):
(WebKit::NetworkCacheStorage::removeEntry):
(WebKit::NetworkCacheStorage::store):
(WebKit::NetworkCacheStorage::setMaximumSize):
(WebKit::NetworkCacheStorage::clear):
(WebKit::NetworkCacheStorage::shrinkIfNeeded):
(WebKit::NetworkCacheStorage::initializeKeyFilter): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (179051 => 179052)


--- trunk/Source/WebKit2/ChangeLog	2015-01-24 02:20:22 UTC (rev 179051)
+++ trunk/Source/WebKit2/ChangeLog	2015-01-24 02:27:31 UTC (rev 179052)
@@ -1,3 +1,25 @@
+2015-01-23  Antti Koivisto  <[email protected]>
+
+        Implement cache size limit
+        https://bugs.webkit.org/show_bug.cgi?id=140844
+
+        Reviewed by Andreas Kling.
+
+        Prevent the cache from growing without bounds. The simple scheme implemented here
+        estimates the cache size from number of entries. When the estimated size exceeds
+        the maximum size we randomly clear 1/4 of the entries.
+
+        * NetworkProcess/cache/NetworkCacheStorage.h:
+        * NetworkProcess/cache/NetworkCacheStorageCocoa.mm:
+        (WebKit::NetworkCacheStorage::NetworkCacheStorage):
+        (WebKit::NetworkCacheStorage::initialize):
+        (WebKit::NetworkCacheStorage::removeEntry):
+        (WebKit::NetworkCacheStorage::store):
+        (WebKit::NetworkCacheStorage::setMaximumSize):
+        (WebKit::NetworkCacheStorage::clear):
+        (WebKit::NetworkCacheStorage::shrinkIfNeeded):
+        (WebKit::NetworkCacheStorage::initializeKeyFilter): Deleted.
+
 2015-01-23  Timothy Horton  <[email protected]>
 
         Fix the pre-Yosemite build.

Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h (179051 => 179052)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h	2015-01-24 02:20:22 UTC (rev 179051)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h	2015-01-24 02:27:31 UTC (rev 179052)
@@ -96,7 +96,8 @@
 private:
     NetworkCacheStorage(const String& directoryPath);
 
-    void initializeKeyFilter();
+    void initialize();
+    void shrinkIfNeeded();
 
     void removeEntry(const NetworkCacheKey&);
 
@@ -109,12 +110,14 @@
 
     const String m_directoryPath;
 
-    size_t m_maximumSize;
+    size_t m_maximumSize { std::numeric_limits<size_t>::max() };
 
     BloomFilter<20> m_keyFilter;
+    std::atomic<size_t> m_approximateEntryCount { 0 };
+    std::atomic<bool> m_shrinkInProgress { false };
 
     Vector<Deque<RetrieveOperation>> m_pendingRetrieveOperationsByPriority;
-    unsigned m_activeRetrieveOperationCount;
+    unsigned m_activeRetrieveOperationCount { 0 };
 
 #if PLATFORM(COCOA)
     mutable OSObjectPtr<dispatch_queue_t> m_ioQueue;

Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm (179051 => 179052)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm	2015-01-24 02:20:22 UTC (rev 179051)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm	2015-01-24 02:27:31 UTC (rev 179052)
@@ -122,30 +122,30 @@
 
 NetworkCacheStorage::NetworkCacheStorage(const String& directoryPath)
     : m_directoryPath(directoryPath)
-    , m_maximumSize(std::numeric_limits<size_t>::max())
-    , m_activeRetrieveOperationCount(0)
     , m_ioQueue(adoptOSObject(dispatch_queue_create("com.apple.WebKit.Cache.Storage", DISPATCH_QUEUE_CONCURRENT)))
     , m_backgroundIOQueue(adoptOSObject(dispatch_queue_create("com.apple.WebKit.Cache.Storage.Background", DISPATCH_QUEUE_CONCURRENT)))
 {
     dispatch_set_target_queue(m_backgroundIOQueue.get(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0));
 
-    initializeKeyFilter();
+    initialize();
 }
 
-void NetworkCacheStorage::initializeKeyFilter()
+void NetworkCacheStorage::initialize()
 {
     ASSERT(RunLoop::isMain());
 
     StringCapture cachePathCapture(m_directoryPath);
     auto& keyFilter = m_keyFilter;
+    auto& entryCount = m_approximateEntryCount;
 
-    dispatch_async(m_backgroundIOQueue.get(), [cachePathCapture, &keyFilter] {
+    dispatch_async(m_backgroundIOQueue.get(), [cachePathCapture, &keyFilter, &entryCount] {
         String cachePath = cachePathCapture.string();
-        traverseCacheFiles(cachePath, [&keyFilter](const String& fileName, const String&) {
+        traverseCacheFiles(cachePath, [&keyFilter, &entryCount](const String& fileName, const String&) {
             NetworkCacheKey::HashType hash;
             if (!NetworkCacheKey::stringToHash(fileName, hash))
                 return;
             keyFilter.add(hash);
+            ++entryCount;
         });
     });
 }
@@ -343,9 +343,11 @@
         m_keyFilter.remove(key.hash());
 
     StringCapture filePathCapture(filePathForKey(key, m_directoryPath));
-    dispatch_async(m_ioQueue.get(), [filePathCapture] {
+    dispatch_async(m_ioQueue.get(), [this, filePathCapture] {
         CString path = WebCore::fileSystemRepresentation(filePathCapture.string());
         unlink(path.data());
+        if (m_approximateEntryCount)
+            --m_approximateEntryCount;
     });
 }
 
@@ -427,8 +429,11 @@
         dispatch_io_write(channel.get(), 0, data.get(), dispatch_get_main_queue(), [this, key, completionHandler](bool done, dispatch_data_t, int error) {
             ASSERT_UNUSED(done, done);
             LOG(NetworkCacheStorage, "(NetworkProcess) write complete error=%d", error);
-            if (!error)
+            if (!error) {
                 m_keyFilter.add(key.hash());
+                ++m_approximateEntryCount;
+                shrinkIfNeeded();
+            }
             completionHandler(!error);
         });
     });
@@ -437,8 +442,9 @@
 void NetworkCacheStorage::setMaximumSize(size_t size)
 {
     ASSERT(RunLoop::isMain());
-    // FIXME: Implement.
     m_maximumSize = size;
+
+    shrinkIfNeeded();
 }
 
 void NetworkCacheStorage::clear()
@@ -447,6 +453,7 @@
     LOG(NetworkCacheStorage, "(NetworkProcess) clearing cache");
 
     m_keyFilter.clear();
+    m_approximateEntryCount = 0;
 
     StringCapture directoryPathCapture(m_directoryPath);
 
@@ -463,6 +470,51 @@
     });
 }
 
+void NetworkCacheStorage::shrinkIfNeeded()
+{
+    const size_t assumedAverageResourceSize { 48 * 1024 };
+    const size_t everyNthResourceToDelete { 4 };
+
+    size_t estimatedCacheSize = assumedAverageResourceSize * m_approximateEntryCount;
+
+    if (estimatedCacheSize <= m_maximumSize)
+        return;
+    if (m_shrinkInProgress)
+        return;
+    m_shrinkInProgress = true;
+
+    LOG(NetworkCacheStorage, "(NetworkProcess) shrinking cache m_approximateEntryCount=%d estimatedCacheSize=%d, m_maximumSize=%d", static_cast<size_t>(m_approximateEntryCount), estimatedCacheSize, m_maximumSize);
+
+    StringCapture cachePathCapture(m_directoryPath);
+    dispatch_async(m_backgroundIOQueue.get(), [this, cachePathCapture] {
+        String cachePath = cachePathCapture.string();
+        size_t foundEntryCount = 0;
+        size_t deletedCount = 0;
+        traverseCacheFiles(cachePath, [this, &foundEntryCount, &deletedCount](const String& fileName, const String& directory) {
+            String partitionPath = WebCore::pathByAppendingComponent(directory, fileName);
+            CString path = WebCore::fileSystemRepresentation(partitionPath);
+            ++foundEntryCount;
+            if (foundEntryCount % everyNthResourceToDelete)
+                return;
+            ++deletedCount;
+
+            unlink(path.data());
+
+            NetworkCacheKey::HashType hash;
+            if (!NetworkCacheKey::stringToHash(fileName, hash))
+                return;
+            dispatch_async(dispatch_get_main_queue(), [this, hash] {
+                if (m_keyFilter.mayContain(hash))
+                    m_keyFilter.remove(hash);
+            });
+        });
+        m_approximateEntryCount = foundEntryCount - deletedCount;
+        m_shrinkInProgress = false;
+
+        LOG(NetworkCacheStorage, "(NetworkProcess) cache shrink completed m_approximateEntryCount=%d", static_cast<size_t>(m_approximateEntryCount));
+    });
 }
 
+}
+
 #endif
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to