Browse Source

LibWebView: Reduce overhead of updating a cookie's last access time

Getting a document's cookie value currently involves:

1. Doing a large SELECT statement and filtering the results to match
   the document and some query parameters based on the cookie RFC.
2. For every cookie selected this way, doing an UPDATE to set its last
   access time.
3. For every UPDATE, do a DELETE to remove all expired cookies.

There's no need to perform cookie expiration for every UPDATE. Instead,
we can do the expiration once after all the UPDATEs are complete.

This reduces time spent waiting for cookies on https://twinings.co.uk
from ~1.9s to ~1.3s on my machine.
Timothy Flynn 1 năm trước cách đây
mục cha
commit
f1d6693990

+ 24 - 1
Userland/Libraries/LibWebView/CookieJar.cpp

@@ -55,6 +55,10 @@ ErrorOr<CookieJar> CookieJar::create(Database& database)
             persistent=?
         WHERE ((name = ?) AND (domain = ?) AND (path = ?));)#"sv));
 
+    statements.update_cookie_last_access_time = TRY(database.prepare_statement(R"#(
+        UPDATE Cookies SET last_access_time=?
+        WHERE ((name = ?) AND (domain = ?) AND (path = ?));)#"sv));
+
     statements.insert_cookie = TRY(database.prepare_statement("INSERT INTO Cookies VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"sv));
     statements.expire_cookie = TRY(database.prepare_statement("DELETE FROM Cookies WHERE (expiry_time < ?);"sv));
     statements.select_cookie = TRY(database.prepare_statement("SELECT * FROM Cookies WHERE ((name = ?) AND (domain = ?) AND (path = ?));"sv));
@@ -447,9 +451,10 @@ Vector<Web::Cookie::Cookie> CookieJar::get_matching_cookies(const URL& url, Stri
 
     for (auto& cookie : cookie_list) {
         cookie.last_access_time = now;
-        update_cookie_in_database(cookie);
+        update_cookie_last_access_time_in_database(cookie);
     }
 
+    purge_expired_cookies();
     return cookie_list;
 }
 
@@ -567,6 +572,24 @@ void CookieJar::update_cookie_in_database(Web::Cookie::Cookie const& cookie)
         });
 }
 
+void CookieJar::update_cookie_last_access_time_in_database(Web::Cookie::Cookie const& cookie)
+{
+    m_storage.visit(
+        [&](PersistedStorage& storage) {
+            storage.database.execute_statement(
+                storage.statements.update_cookie_last_access_time,
+                {}, {}, {},
+                cookie.last_access_time,
+                cookie.name,
+                cookie.domain,
+                cookie.path);
+        },
+        [&](TransientStorage& storage) {
+            CookieStorageKey key { cookie.name, cookie.domain, cookie.path };
+            storage.set(key, cookie);
+        });
+}
+
 struct WrappedCookie : public RefCounted<WrappedCookie> {
     explicit WrappedCookie(Web::Cookie::Cookie cookie_)
         : RefCounted()

+ 2 - 0
Userland/Libraries/LibWebView/CookieJar.h

@@ -33,6 +33,7 @@ class CookieJar {
         SQL::StatementID create_table { 0 };
         SQL::StatementID insert_cookie { 0 };
         SQL::StatementID update_cookie { 0 };
+        SQL::StatementID update_cookie_last_access_time { 0 };
         SQL::StatementID expire_cookie { 0 };
         SQL::StatementID select_cookie { 0 };
         SQL::StatementID select_all_cookies { 0 };
@@ -76,6 +77,7 @@ private:
 
     void insert_cookie_into_database(Web::Cookie::Cookie const& cookie);
     void update_cookie_in_database(Web::Cookie::Cookie const& cookie);
+    void update_cookie_last_access_time_in_database(Web::Cookie::Cookie const& cookie);
 
     using OnCookieFound = Function<void(Web::Cookie::Cookie&, Web::Cookie::Cookie)>;
     using OnCookieNotFound = Function<void(Web::Cookie::Cookie)>;