⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 179823 in webkit


Ignore:
Timestamp:
Feb 9, 2015, 3:03:06 AM (12 years ago)
Author:
Antti Koivisto
Message:

Measure cache size more accurately
https://bugs.webkit.org/show_bug.cgi?id=141378
<rdar://problem/19760224>

Reviewed by Chris Dumez.

Estimate the cache disk space usage from the actual entry sizes instead of the item count.
This prevents large cache items from making the cache grow beyond its bounds.

  • NetworkProcess/cache/NetworkCacheStorage.h:
  • NetworkProcess/cache/NetworkCacheStorageCocoa.mm:

(WebKit::NetworkCacheStorage::initialize):
(WebKit::NetworkCacheStorage::removeEntry):
(WebKit::NetworkCacheStorage::store):
(WebKit::NetworkCacheStorage::clear):
(WebKit::NetworkCacheStorage::shrinkIfNeeded):

Location:
trunk/Source/WebKit2
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r179821 r179823  
     12015-02-08  Antti Koivisto  <antti@apple.com>
     2
     3        Measure cache size more accurately
     4        https://bugs.webkit.org/show_bug.cgi?id=141378
     5        <rdar://problem/19760224>
     6
     7        Reviewed by Chris Dumez.
     8
     9        Estimate the cache disk space usage from the actual entry sizes instead of the item count.
     10        This prevents large cache items from making the cache grow beyond its bounds.
     11
     12        * NetworkProcess/cache/NetworkCacheStorage.h:
     13        * NetworkProcess/cache/NetworkCacheStorageCocoa.mm:
     14        (WebKit::NetworkCacheStorage::initialize):
     15        (WebKit::NetworkCacheStorage::removeEntry):
     16        (WebKit::NetworkCacheStorage::store):
     17        (WebKit::NetworkCacheStorage::clear):
     18        (WebKit::NetworkCacheStorage::shrinkIfNeeded):
     19
    1202015-02-09  Carlos Garcia Campos  <cgarcia@igalia.com>
    221
  • trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h

    r179804 r179823  
    3030
    3131#include "NetworkCacheKey.h"
    32 #include <WebCore/ResourceResponse.h>
    3332#include <wtf/BloomFilter.h>
    3433#include <wtf/Deque.h>
     
    4645
    4746namespace WebKit {
    48 
    49 class ShareableResource;
    5047
    5148#if PLATFORM(COCOA)
     
    193190
    194191    BloomFilter<20> m_contentsFilter;
    195     std::atomic<size_t> m_approximateEntryCount { 0 };
     192    std::atomic<size_t> m_approximateSize { 0 };
    196193    std::atomic<bool> m_shrinkInProgress { false };
    197194
  • trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm

    r179804 r179823  
    3535#include <sys/mman.h>
    3636#include <sys/stat.h>
     37#include <wtf/RandomNumber.h>
    3738#include <wtf/RunLoop.h>
    3839#include <wtf/text/CString.h>
     
    110111
    111112    StringCapture cachePathCapture(m_directoryPath);
    112     auto& entryCount = m_approximateEntryCount;
    113 
    114     dispatch_async(m_backgroundIOQueue.get(), [this, cachePathCapture, &entryCount] {
     113
     114    dispatch_async(m_backgroundIOQueue.get(), [this, cachePathCapture] {
    115115        String cachePath = cachePathCapture.string();
    116         traverseCacheFiles(cachePath, [this, &entryCount](const String& fileName, const String&) {
     116        traverseCacheFiles(cachePath, [this](const String& fileName, const String& partitionPath) {
    117117            NetworkCacheKey::HashType hash;
    118118            if (!NetworkCacheKey::stringToHash(fileName, hash))
     
    122122                m_contentsFilter.add(shortHash);
    123123            });
    124             ++entryCount;
     124            auto filePath = WebCore::pathByAppendingComponent(partitionPath, fileName);
     125            long long fileSize = 0;
     126            WebCore::getFileSize(filePath, fileSize);
     127            m_approximateSize += fileSize;
    125128        });
    126129    });
     
    324327    ASSERT(RunLoop::isMain());
    325328
     329    // For simplicity we don't reduce m_approximateSize on removals caused by load or decode errors.
     330    // The next cache shrink will update the size.
     331
    326332    if (m_contentsFilter.mayContain(key.shortHash()))
    327333        m_contentsFilter.remove(key.shortHash());
    328334
    329335    StringCapture filePathCapture(filePathForKey(key, m_directoryPath));
    330     dispatch_async(m_ioQueue.get(), [this, filePathCapture] {
     336    dispatch_async(m_backgroundIOQueue.get(), [this, filePathCapture] {
    331337        WebCore::deleteFile(filePathCapture.string());
    332         if (m_approximateEntryCount)
    333             --m_approximateEntryCount;
    334338    });
    335339}
     
    430434
    431435    m_contentsFilter.add(key.shortHash());
    432     ++m_approximateEntryCount;
    433436
    434437    auto storeOperation = std::make_unique<StoreOperation>(StoreOperation { key, entry, WTF::move(completionHandler) });
     
    442445
    443446        size_t bodyOffset = dispatch_data_get_size(encodedHeader.get());
    444         size_t bodySize = store.entry.body.size();
    445447
    446448        int fd;
    447449        auto channel = openFileForKey(store.key, FileOpenType::Create, cachePathCapture.string(), fd);
    448         dispatch_io_write(channel.get(), 0, writeData.get(), dispatch_get_main_queue(), [this, &store, fd, bodyOffset, bodySize](bool done, dispatch_data_t, int error) {
     450        dispatch_io_write(channel.get(), 0, writeData.get(), dispatch_get_main_queue(), [this, &store, fd, bodyOffset](bool done, dispatch_data_t, int error) {
    449451            ASSERT_UNUSED(done, done);
    450452            LOG(NetworkCacheStorage, "(NetworkProcess) write complete error=%d", error);
     
    452454                if (m_contentsFilter.mayContain(store.key.shortHash()))
    453455                    m_contentsFilter.remove(store.key.shortHash());
    454                 if (m_approximateEntryCount)
    455                     --m_approximateEntryCount;
    456456            }
     457            size_t bodySize = store.entry.body.size();
     458            size_t totalSize = bodyOffset + bodySize;
     459
     460            m_approximateSize += totalSize;
    457461
    458462            bool shouldMapBody = !error && bodySize >= vm_page_size;
     
    532536
    533537    m_contentsFilter.clear();
    534     m_approximateEntryCount = 0;
     538    m_approximateSize = 0;
    535539
    536540    StringCapture directoryPathCapture(m_directoryPath);
     
    550554void NetworkCacheStorage::shrinkIfNeeded()
    551555{
    552     const size_t assumedAverageResourceSize { 48 * 1024 };
    553     const size_t everyNthResourceToDelete { 4 };
    554 
    555     size_t estimatedCacheSize = assumedAverageResourceSize * m_approximateEntryCount;
    556 
    557     if (estimatedCacheSize <= m_maximumSize)
     556    ASSERT(RunLoop::isMain());
     557
     558    static const double deletionProbability { 0.25 };
     559
     560    if (m_approximateSize <= m_maximumSize)
    558561        return;
    559562    if (m_shrinkInProgress)
     
    561564    m_shrinkInProgress = true;
    562565
    563     LOG(NetworkCacheStorage, "(NetworkProcess) shrinking cache m_approximateEntryCount=%d estimatedCacheSize=%d, m_maximumSize=%d", static_cast<size_t>(m_approximateEntryCount), estimatedCacheSize, m_maximumSize);
     566    LOG(NetworkCacheStorage, "(NetworkProcess) shrinking cache approximateSize=%d, m_maximumSize=%d", static_cast<size_t>(m_approximateSize), m_maximumSize);
     567
     568    m_approximateSize = 0;
    564569
    565570    StringCapture cachePathCapture(m_directoryPath);
    566571    dispatch_async(m_backgroundIOQueue.get(), [this, cachePathCapture] {
    567572        String cachePath = cachePathCapture.string();
    568         size_t foundEntryCount = 0;
    569         size_t deletedCount = 0;
    570         traverseCacheFiles(cachePath, [this, &foundEntryCount, &deletedCount](const String& fileName, const String& partitionPath) {
    571             ++foundEntryCount;
    572             if (foundEntryCount % everyNthResourceToDelete)
     573        traverseCacheFiles(cachePath, [this](const String& fileName, const String& partitionPath) {
     574            auto filePath = WebCore::pathByAppendingComponent(partitionPath, fileName);
     575
     576            bool shouldDelete = randomNumber() < deletionProbability;
     577            if (!shouldDelete) {
     578                long long fileSize = 0;
     579                WebCore::getFileSize(filePath, fileSize);
     580                m_approximateSize += fileSize;
    573581                return;
    574             ++deletedCount;
    575 
    576             WebCore::deleteFile(WebCore::pathByAppendingComponent(partitionPath, fileName));
    577 
     582            }
     583
     584            WebCore::deleteFile(filePath);
    578585            NetworkCacheKey::HashType hash;
    579586            if (!NetworkCacheKey::stringToHash(fileName, hash))
     
    585592            });
    586593        });
    587         m_approximateEntryCount = foundEntryCount - deletedCount;
    588594        m_shrinkInProgress = false;
    589595
    590         LOG(NetworkCacheStorage, "(NetworkProcess) cache shrink completed m_approximateEntryCount=%d", static_cast<size_t>(m_approximateEntryCount));
     596        LOG(NetworkCacheStorage, "(NetworkProcess) cache shrink completed approximateSize=%d", static_cast<size_t>(m_approximateSize));
    591597    });
    592598}
Note: See TracChangeset for help on using the changeset viewer.