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

Changeset 278786 in webkit


Ignore:
Timestamp:
Jun 11, 2021, 3:56:18 PM (5 years ago)
Author:
Chris Dumez
Message:

[WK2] Batch local storage database writes using transactions
​https://bugs.webkit.org/show_bug.cgi?id=226938

Reviewed by Geoff Garen.

Batch local storage writes using transactions, to improve performance
and reduce disk writes. In this patch, we use a simple time-based
approach where we batch transactions happening in the same 500ms
period.

  • NetworkProcess/WebStorage/LocalStorageDatabase.cpp:

(WebKit::LocalStorageDatabase::create):
(WebKit::LocalStorageDatabase::LocalStorageDatabase):
(WebKit::LocalStorageDatabase::startTransactionIfNecessary):
(WebKit::LocalStorageDatabase::removeItem):
(WebKit::LocalStorageDatabase::setItem):
(WebKit::LocalStorageDatabase::clear):
(WebKit::LocalStorageDatabase::close):

  • NetworkProcess/WebStorage/LocalStorageDatabase.h:
  • NetworkProcess/WebStorage/StorageArea.cpp:

(WebKit::StorageArea::ensureDatabase const):

Location:
trunk/Source/WebKit
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r278783 r278786  
     12021-06-11  Chris Dumez  <cdumez@apple.com>
     2
     3        [WK2] Batch local storage database writes using transactions
     4        https://bugs.webkit.org/show_bug.cgi?id=226938
     5
     6        Reviewed by Geoff Garen.
     7
     8        Batch local storage writes using transactions, to improve performance
     9        and reduce disk writes. In this patch, we use a simple time-based
     10        approach where we batch transactions happening in the same 500ms
     11        period.
     12
     13        * NetworkProcess/WebStorage/LocalStorageDatabase.cpp:
     14        (WebKit::LocalStorageDatabase::create):
     15        (WebKit::LocalStorageDatabase::LocalStorageDatabase):
     16        (WebKit::LocalStorageDatabase::startTransactionIfNecessary):
     17        (WebKit::LocalStorageDatabase::removeItem):
     18        (WebKit::LocalStorageDatabase::setItem):
     19        (WebKit::LocalStorageDatabase::clear):
     20        (WebKit::LocalStorageDatabase::close):
     21        * NetworkProcess/WebStorage/LocalStorageDatabase.h:
     22        * NetworkProcess/WebStorage/StorageArea.cpp:
     23        (WebKit::StorageArea::ensureDatabase const):
     24
    1252021-06-11  Alex Christensen  <achristensen@webkit.org>
    226
  • trunk/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.cpp

    r278778 r278786  
    4141constexpr auto getItemsQueryString { "SELECT key, value FROM ItemTable"_s };
    4242constexpr unsigned maximumSizeForValuesKeptInMemory { 1024 }; // 1 KB
    43 
    44 Ref<LocalStorageDatabase> LocalStorageDatabase::create(String&& databasePath, unsigned quotaInBytes)
    45 {
    46     return adoptRef(*new LocalStorageDatabase(WTFMove(databasePath), quotaInBytes));
    47 }
    48 
    49 LocalStorageDatabase::LocalStorageDatabase(String&& databasePath, unsigned quotaInBytes)
    50     : m_databasePath(WTFMove(databasePath))
     43constexpr Seconds transactionDuration { 500_ms };
     44
     45Ref<LocalStorageDatabase> LocalStorageDatabase::create(Ref<WorkQueue>&& workQueue, String&& databasePath, unsigned quotaInBytes)
     46{
     47    return adoptRef(*new LocalStorageDatabase(WTFMove(workQueue), WTFMove(databasePath), quotaInBytes));
     48}
     49
     50LocalStorageDatabase::LocalStorageDatabase(Ref<WorkQueue>&& workQueue, String&& databasePath, unsigned quotaInBytes)
     51    : m_workQueue(WTFMove(workQueue))
     52    , m_databasePath(WTFMove(databasePath))
    5153    , m_quotaInBytes(quotaInBytes)
    5254{
    … …  
    99101
    100102    return true;
     103}
     104
     105void LocalStorageDatabase::startTransactionIfNecessary()
     106{
     107    if (!m_transaction)
     108        m_transaction = makeUnique<SQLiteTransaction>(m_database);
     109
     110    if (m_transaction->inProgress())
     111        return;
     112
     113    m_transaction->begin();
     114    m_workQueue->dispatchAfter(transactionDuration, [weakThis = makeWeakPtr(*this)] {
     115        if (weakThis)
     116            weakThis->m_transaction->commit();
     117    });
    101118}
    102119
    … …  
    185202        return;
    186203
     204    startTransactionIfNecessary();
    187205    oldValue = item(key);
    188206    if (oldValue.isNull())
    … …  
    249267        return;
    250268
     269    startTransactionIfNecessary();
    251270    oldValue = item(key);
    252271
    … …  
    281300        return false;
    282301
     302    startTransactionIfNecessary();
    283303    auto clearStatement = scopedStatement(m_clearStatement, "DELETE FROM ItemTable"_s);
    284304    if (!clearStatement) {
    … …  
    299319
    300320    return m_database.lastChanges() > 0;
     321}
     322
     323void LocalStorageDatabase::flushToDisk()
     324{
     325    if (m_transaction)
     326        m_transaction->commit();
    301327}
    302328
    … …  
    316342    m_deleteItemStatement = nullptr;
    317343    m_items = std::nullopt;
     344    if (auto transaction = std::exchange(m_transaction, nullptr))
     345        transaction->commit();
    318346
    319347    if (m_database.isOpen())
  • trunk/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.h

    r278778 r278786  
    2828#include <WebCore/SQLiteDatabase.h>
    2929#include <wtf/HashMap.h>
     30#include <wtf/WeakPtr.h>
     31#include <wtf/WorkQueue.h>
    3032
    3133namespace WebCore {
    3234class SQLiteStatementAutoResetScope;
     35class SQLiteTransaction;
    3336
    3437struct SecurityOriginData;
    … …  
    3740namespace WebKit {
    3841
    39 class LocalStorageDatabase : public RefCounted<LocalStorageDatabase> {
     42class LocalStorageDatabase : public RefCounted<LocalStorageDatabase>, public CanMakeWeakPtr<LocalStorageDatabase> {
    4043public:
    41     static Ref<LocalStorageDatabase> create(String&& databasePath, unsigned quotaInBytes);
     44    static Ref<LocalStorageDatabase> create(Ref<WorkQueue>&&, String&& databasePath, unsigned quotaInBytes);
    4245    ~LocalStorageDatabase();
    4346
    … …  
    5255    void close();
    5356
     57    void flushToDisk();
    5458    void handleLowMemoryWarning();
    5559
    5660private:
    57     LocalStorageDatabase(String&& databasePath, unsigned quotaInBytes);
     61    LocalStorageDatabase(Ref<WorkQueue>&&, String&& databasePath, unsigned quotaInBytes);
    5862
    5963    enum class ShouldCreateDatabase : bool { No, Yes };
    6064    bool openDatabase(ShouldCreateDatabase);
    6165
     66    void startTransactionIfNecessary();
    6267    bool migrateItemTableIfNeeded();
    6368    bool databaseIsEmpty() const;
    … …  
    6772    WebCore::SQLiteStatementAutoResetScope scopedStatement(std::unique_ptr<WebCore::SQLiteStatement>&, ASCIILiteral query) const;
    6873
     74    Ref<WorkQueue> m_workQueue;
    6975    String m_databasePath;
    7076    mutable WebCore::SQLiteDatabase m_database;
     77    std::unique_ptr<WebCore::SQLiteTransaction> m_transaction;
    7178    const unsigned m_quotaInBytes { 0 };
    7279    bool m_isClosed { false };
  • trunk/Source/WebKit/NetworkProcess/WebStorage/StorageArea.cpp

    r278409 r278786  
    176176    if (!m_localStorageDatabase) {
    177177        auto* localStorageDatabaseTracker = m_localStorageNamespace->storageManager()->localStorageDatabaseTracker();
    178         m_localStorageDatabase = LocalStorageDatabase::create(localStorageDatabaseTracker->databasePath(m_securityOrigin), m_quotaInBytes);
     178        m_localStorageDatabase = LocalStorageDatabase::create(m_queue.copyRef(), localStorageDatabaseTracker->databasePath(m_securityOrigin), m_quotaInBytes);
    179179        m_localStorageDatabase->openIfExisting();
    180180    }
    … …  
    200200}
    201201
     202void StorageArea::syncToDatabase()
     203{
     204    if (m_localStorageDatabase)
     205        m_localStorageDatabase->flushToDisk();
     206}
     207
    202208void StorageArea::handleLowMemoryWarning()
    203209{
  • trunk/Source/WebKit/NetworkProcess/WebStorage/StorageArea.h

    r276659 r278786  
    7272    void close();
    7373
     74    void syncToDatabase();
    7475    void handleLowMemoryWarning();
    7576
  • trunk/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.cpp

    r278185 r278786  
    156156    ASSERT(RunLoop::isMain());
    157157
    158     m_queue->dispatchSync([] { });
     158    BinarySemaphore semaphore;
     159    m_queue->dispatch([this, &semaphore] {
     160        for (const auto& storageArea : m_storageAreas.values()) {
     161            ASSERT(storageArea);
     162            if (storageArea)
     163                storageArea->syncToDatabase();
     164        }
     165        semaphore.signal();
     166    });
     167    semaphore.wait();
    159168}
    160169
Note: See TracChangeset for help on using the changeset viewer.