Changeset 179547 in webkit


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

Memory cache for resources pending disk write
https://bugs.webkit.org/show_bug.cgi?id=141159

Reviewed by Andreas Kling.

If a resource was requested from the disk cache before it has been written we ended up
loading it again. Add a short lived memory cache to avoid this.

  • NetworkProcess/cache/NetworkCache.cpp:

(WebKit::decodeStorageEntry):

  • NetworkProcess/cache/NetworkCacheStorage.h:

(WebKit::NetworkCacheStorage::Data::isMap):

Add a way to know whether a Data is backed by map or not. SharedMemory does not work correctly
if it is not a map.

  • NetworkProcess/cache/NetworkCacheStorageCocoa.mm:

(WebKit::NetworkCacheStorage::Data::Data):
(WebKit::NetworkCacheStorage::initialize):

Also do some renaming.

(WebKit::decodeEntry):
(WebKit::NetworkCacheStorage::removeEntry):
(WebKit::NetworkCacheStorage::retrieve):
(WebKit::NetworkCacheStorage::store):
(WebKit::NetworkCacheStorage::clear):
(WebKit::NetworkCacheStorage::shrinkIfNeeded):

Location:
trunk/Source/WebKit2
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r179546 r179547  
     12015-02-03  Antti Koivisto  <antti@apple.com>
     2
     3        Memory cache for resources pending disk write
     4        https://bugs.webkit.org/show_bug.cgi?id=141159
     5
     6        Reviewed by Andreas Kling.
     7
     8        If a resource was requested from the disk cache before it has been written we ended up
     9        loading it again. Add a short lived memory cache to avoid this.
     10
     11        * NetworkProcess/cache/NetworkCache.cpp:
     12        (WebKit::decodeStorageEntry):
     13        * NetworkProcess/cache/NetworkCacheStorage.h:
     14        (WebKit::NetworkCacheStorage::Data::isMap):
     15
     16            Add a way to know whether a Data is backed by map or not. SharedMemory does not work correctly
     17            if it is not a map.
     18
     19        * NetworkProcess/cache/NetworkCacheStorageCocoa.mm:
     20        (WebKit::NetworkCacheStorage::Data::Data):
     21        (WebKit::NetworkCacheStorage::initialize):
     22
     23            Also do some renaming.
     24
     25        (WebKit::decodeEntry):
     26        (WebKit::NetworkCacheStorage::removeEntry):
     27        (WebKit::NetworkCacheStorage::retrieve):
     28        (WebKit::NetworkCacheStorage::store):
     29        (WebKit::NetworkCacheStorage::clear):
     30        (WebKit::NetworkCacheStorage::shrinkIfNeeded):
     31
    1322015-02-02  Antti Koivisto  <antti@apple.com>
    233
  • trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp

    r179546 r179547  
    175175
    176176#if ENABLE(SHAREABLE_RESOURCE)
    177     RefPtr<SharedMemory> sharedMemory = storageEntry.body.size() ? SharedMemory::createFromVMBuffer(const_cast<uint8_t*>(storageEntry.body.data()), storageEntry.body.size()) : nullptr;
     177    RefPtr<SharedMemory> sharedMemory = storageEntry.body.isMap() ? SharedMemory::createFromVMBuffer(const_cast<uint8_t*>(storageEntry.body.data()), storageEntry.body.size()) : nullptr;
    178178    RefPtr<ShareableResource> shareableResource = sharedMemory ? ShareableResource::create(sharedMemory.release(), 0, storageEntry.body.size()) : nullptr;
    179179
  • trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h

    r179546 r179547  
    106106    class Data {
    107107    public:
    108         Data();
     108        Data() { }
    109109        Data(const uint8_t*, size_t);
     110
     111        enum class Backing { Buffer, Map };
    110112#if PLATFORM(COCOA)
    111         explicit Data(DispatchPtr<dispatch_data_t>);
     113        explicit Data(DispatchPtr<dispatch_data_t>, Backing = Backing::Buffer);
    112114#endif
    113115        bool isNull() const;
     
    115117        const uint8_t* data() const;
    116118        size_t size() const { return m_size; }
     119        bool isMap() const { return m_isMap; }
    117120
    118121#if PLATFORM(COCOA)
     
    123126        mutable DispatchPtr<dispatch_data_t> m_dispatchData;
    124127#endif
    125         mutable const uint8_t* m_data;
    126         size_t m_size;
     128        mutable const uint8_t* m_data { nullptr };
     129        size_t m_size { 0 };
     130        bool m_isMap { false };
    127131    };
    128132
     
    161165    size_t m_maximumSize { std::numeric_limits<size_t>::max() };
    162166
    163     BloomFilter<20> m_keyFilter;
     167    BloomFilter<20> m_contentsFilter;
    164168    std::atomic<size_t> m_approximateEntryCount { 0 };
    165169    std::atomic<bool> m_shrinkInProgress { false };
     
    167171    Vector<Deque<RetrieveOperation>> m_pendingRetrieveOperationsByPriority;
    168172    unsigned m_activeRetrieveOperationCount { 0 };
     173
     174    typedef std::pair<NetworkCacheKey, Entry> KeyEntryPair;
     175    HashMap<NetworkCacheKey::HashType, std::shared_ptr<KeyEntryPair>, AlreadyHashed> m_writeCache;
    169176
    170177#if PLATFORM(COCOA)
  • trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm

    r179546 r179547  
    7474}
    7575
    76 NetworkCacheStorage::Data::Data()
    77     : m_data(nullptr)
    78     , m_size(0)
    79 {
    80 }
    81 
    8276NetworkCacheStorage::Data::Data(const uint8_t* data, size_t size)
    8377    : m_dispatchData(adoptDispatch(dispatch_data_create(data, size, nullptr, DISPATCH_DATA_DESTRUCTOR_DEFAULT)))
    84     , m_data(nullptr)
    8578    , m_size(size)
    8679{
    8780}
    8881
    89 NetworkCacheStorage::Data::Data(DispatchPtr<dispatch_data_t> dispatchData)
     82NetworkCacheStorage::Data::Data(DispatchPtr<dispatch_data_t> dispatchData, Backing backing)
    9083{
    9184    const void* data;
    9285    m_dispatchData = adoptDispatch(dispatch_data_create_map(dispatchData.get(), &data, &m_size));
    9386    m_data = static_cast<const uint8_t*>(data);
     87    m_isMap = m_size && backing == Backing::Map;
    9488}
    9589
     
    136130
    137131    StringCapture cachePathCapture(m_directoryPath);
    138     auto& keyFilter = m_keyFilter;
     132    auto& diskContentsFilter = m_contentsFilter;
    139133    auto& entryCount = m_approximateEntryCount;
    140134
    141     dispatch_async(m_backgroundIOQueue.get(), [cachePathCapture, &keyFilter, &entryCount] {
     135    dispatch_async(m_backgroundIOQueue.get(), [cachePathCapture, &diskContentsFilter, &entryCount] {
    142136        String cachePath = cachePathCapture.string();
    143         traverseCacheFiles(cachePath, [&keyFilter, &entryCount](const String& fileName, const String&) {
     137        traverseCacheFiles(cachePath, [&diskContentsFilter, &entryCount](const String& fileName, const String&) {
    144138            NetworkCacheKey::HashType hash;
    145139            if (!NetworkCacheKey::stringToHash(fileName, hash))
    146140                return;
    147             keyFilter.add(hash);
     141            diskContentsFilter.add(hash);
    148142            ++entryCount;
    149143        });
     
    294288    return std::make_unique<NetworkCacheStorage::Entry>(NetworkCacheStorage::Entry {
    295289        metaData.timeStamp,
    296         NetworkCacheStorage::Data(headerData),
    297         NetworkCacheStorage::Data(bodyData)
     290        NetworkCacheStorage::Data { headerData },
     291        NetworkCacheStorage::Data { bodyData, NetworkCacheStorage::Data::Backing::Map }
    298292    });
    299293}
     
    347341    ASSERT(RunLoop::isMain());
    348342
    349     if (m_keyFilter.mayContain(key.hash()))
    350         m_keyFilter.remove(key.hash());
     343    if (m_contentsFilter.mayContain(key.hash()))
     344        m_contentsFilter.remove(key.hash());
    351345
    352346    StringCapture filePathCapture(filePathForKey(key, m_directoryPath));
     
    417411    ASSERT(RunLoop::isMain());
    418412
    419     if (!m_keyFilter.mayContain(key.hash())) {
     413    if (!m_contentsFilter.mayContain(key.hash())) {
    420414        completionHandler(nullptr);
    421415        return;
     416    }
     417
     418    // Write cache is a temporary memory cache used to respond to requests while a write is pending.
     419    if (auto keyEntryPair = m_writeCache.get(key.hash())) {
     420        if (keyEntryPair->first == key) {
     421            LOG(NetworkCacheStorage, "(NetworkProcess) found from the write cache");
     422            dispatch_async(dispatch_get_main_queue(), [keyEntryPair, completionHandler] {
     423                completionHandler(std::make_unique<Entry>(keyEntryPair->second));
     424            });
     425            return;
     426        }
    422427    }
    423428
     
    432437{
    433438    ASSERT(RunLoop::isMain());
     439
     440    m_contentsFilter.add(key.hash());
     441    ++m_approximateEntryCount;
     442
     443    m_writeCache.set(key.hash(), std::make_shared<KeyEntryPair>(key, entry));
    434444
    435445    StringCapture cachePathCapture(m_directoryPath);
     
    442452            ASSERT_UNUSED(done, done);
    443453            LOG(NetworkCacheStorage, "(NetworkProcess) write complete error=%d", error);
    444             if (!error) {
    445                 m_keyFilter.add(key.hash());
    446                 ++m_approximateEntryCount;
    447                 shrinkIfNeeded();
     454            if (error) {
     455                if (m_contentsFilter.mayContain(key.hash()))
     456                    m_contentsFilter.remove(key.hash());
     457                if (m_approximateEntryCount)
     458                    --m_approximateEntryCount;
    448459            }
     460            m_writeCache.remove(key.hash());
     461
    449462            completionHandler(!error);
    450463        });
    451464    });
     465
     466    shrinkIfNeeded();
    452467}
    453468
     
    456471    ASSERT(RunLoop::isMain());
    457472
    458     if (!m_keyFilter.mayContain(key.hash())) {
     473    if (!m_contentsFilter.mayContain(key.hash())) {
    459474        LOG(NetworkCacheStorage, "(NetworkProcess) existing entry not found, storing full entry");
    460475        store(key, updateEntry, completionHandler);
    461476        return;
    462477    }
     478
     479    m_writeCache.set(key.hash(), std::make_shared<KeyEntryPair>(key, updateEntry));
    463480
    464481    // Try to update the header of an existing entry.
     
    485502            if (error)
    486503                removeEntry(key);
     504            m_writeCache.remove(key.hash());
    487505
    488506            completionHandler(!error);
     
    504522    LOG(NetworkCacheStorage, "(NetworkProcess) clearing cache");
    505523
    506     m_keyFilter.clear();
     524    m_writeCache.clear();
     525    m_contentsFilter.clear();
    507526    m_approximateEntryCount = 0;
    508527
     
    556575                return;
    557576            dispatch_async(dispatch_get_main_queue(), [this, hash] {
    558                 if (m_keyFilter.mayContain(hash))
    559                     m_keyFilter.remove(hash);
     577                if (m_contentsFilter.mayContain(hash))
     578                    m_contentsFilter.remove(hash);
    560579            });
    561580        });
Note: See TracChangeset for help on using the changeset viewer.