Changeset 278778 in webkit
- Timestamp:
- Jun 11, 2021, 1:34:28 PM (5 years ago)
- Location:
- trunk/Source/WebKit
- Files:
-
- 3 edited
-
ChangeLog (modified) (1 diff)
-
NetworkProcess/WebStorage/LocalStorageDatabase.cpp (modified) (11 diffs)
-
NetworkProcess/WebStorage/LocalStorageDatabase.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r278772 r278778 1 2021-06-11 Chris Dumez <cdumez@apple.com> 2 3 Regression(r276653) We're going to disk more often for local storage operations 4 https://bugs.webkit.org/show_bug.cgi?id=226832 5 6 Reviewed by Darin Adler. 7 8 We're going to disk more often for local storage operations since r276653 because we no 9 longer keep items in memory. This results in a slightly increased power usage on one of 10 our benchmarks. As a first step to improve this, I am reintroducing a cache of the items 11 in memory, as long as the values are not too large (1Kb limit). We still go to disk to 12 look up values that are larger than 1Kb to avoid regressing memory usage. 13 14 * NetworkProcess/WebStorage/LocalStorageDatabase.cpp: 15 (WebKit::LocalStorageDatabase::openDatabase): 16 (WebKit::LocalStorageDatabase::items const): 17 (WebKit::LocalStorageDatabase::removeItem): 18 (WebKit::LocalStorageDatabase::item const): 19 (WebKit::LocalStorageDatabase::itemBypassingCache const): 20 (WebKit::LocalStorageDatabase::setItem): 21 (WebKit::LocalStorageDatabase::clear): 22 (WebKit::LocalStorageDatabase::close): 23 (WebKit::LocalStorageDatabase::databaseIsEmpty const): 24 * NetworkProcess/WebStorage/LocalStorageDatabase.h: 25 1 26 2021-06-11 Chris Dumez <cdumez@apple.com> 2 27 -
trunk/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.cpp
r278651 r278778 39 39 using namespace WebCore; 40 40 41 static const ASCIILiteral getItemsQueryString { "SELECT key, value FROM ItemTable"_s }; 41 constexpr auto getItemsQueryString { "SELECT key, value FROM ItemTable"_s }; 42 constexpr unsigned maximumSizeForValuesKeptInMemory { 1024 }; // 1 KB 42 43 43 44 Ref<LocalStorageDatabase> LocalStorageDatabase::create(String&& databasePath, unsigned quotaInBytes) … … 62 63 { 63 64 ASSERT(!RunLoop::isMain()); 64 if (!FileSystem::fileExists(m_databasePath) && shouldCreateDatabase == ShouldCreateDatabase::No) 65 return true; 65 if (!FileSystem::fileExists(m_databasePath)) { 66 if (shouldCreateDatabase == ShouldCreateDatabase::No) 67 return true; 68 m_items = HashMap<String, String> { }; 69 } 66 70 67 71 if (m_databasePath.isEmpty()) { … … 141 145 return { }; 142 146 147 HashMap<String, String> items; 148 if (m_items) { 149 items.reserveInitialCapacity(m_items->size()); 150 for (auto& entry : *m_items) { 151 auto value = entry.value.isNull() ? itemBypassingCache(entry.key) : entry.value; 152 items.add(entry.key, WTFMove(value)); 153 } 154 return items; 155 } 156 143 157 auto query = scopedStatement(m_getItemsStatement, getItemsQueryString); 144 158 if (!query) { … … 147 161 } 148 162 149 HashMap<String, String> items;163 m_items = HashMap<String, String> { }; 150 164 int result = query->step(); 151 165 while (result == SQLITE_ROW) { 152 166 String key = query->columnText(0); 153 167 String value = query->columnBlobAsString(1); 154 if (!key.isNull() && !value.isNull()) 168 if (!key.isNull() && !value.isNull()) { 169 m_items->add(key, value.sizeInBytes() > maximumSizeForValuesKeptInMemory ? String() : value); 155 170 items.add(WTFMove(key), WTFMove(value)); 171 } 156 172 result = query->step(); 157 173 } … … 185 201 return; 186 202 } 203 204 if (m_items) 205 m_items->remove(key); 187 206 } 188 207 … … 193 212 return { }; 194 213 214 if (m_items) { 215 // Use find() instead of get() since a null String is a valid value here. 216 auto it = m_items->find(key); 217 if (it == m_items->end()) 218 return { }; 219 if (!it->value.isNull()) 220 return it->value; 221 // The value is too large and needs to be fetched from the database. 222 } 223 return itemBypassingCache(key); 224 } 225 226 String LocalStorageDatabase::itemBypassingCache(const String& key) const 227 { 195 228 auto query = scopedStatement(m_getItemStatement, "SELECT value FROM ItemTable WHERE key=?"_s); 196 229 if (!query) { … … 232 265 if (result == SQLITE_FULL) 233 266 quotaException = true; 234 } 267 return; 268 } 269 270 if (m_items) 271 m_items->set(key, value.sizeInBytes() > maximumSizeForValuesKeptInMemory ? String() : value); 235 272 } 236 273 … … 239 276 ASSERT(!RunLoop::isMain()); 240 277 if (!m_database.isOpen()) 278 return false; 279 280 if (m_items && m_items->isEmpty()) 241 281 return false; 242 282 … … 251 291 LOG_ERROR("Failed to clear all items in the local storage database - %i", result); 252 292 return false; 293 } 294 295 if (m_items) { 296 m_items->clear(); 297 return true; 253 298 } 254 299 … … 270 315 m_getItemsStatement = nullptr; 271 316 m_deleteItemStatement = nullptr; 317 m_items = std::nullopt; 272 318 273 319 if (m_database.isOpen()) … … 283 329 if (!m_database.isOpen()) 284 330 return false; 331 332 if (m_items) 333 return m_items->isEmpty(); 285 334 286 335 auto query = m_database.prepareStatement("SELECT COUNT(*) FROM ItemTable"_s); -
trunk/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.h
r278651 r278778 63 63 bool databaseIsEmpty() const; 64 64 65 String itemBypassingCache(const String& key) const; 66 65 67 WebCore::SQLiteStatementAutoResetScope scopedStatement(std::unique_ptr<WebCore::SQLiteStatement>&, ASCIILiteral query) const; 66 68 … … 69 71 const unsigned m_quotaInBytes { 0 }; 70 72 bool m_isClosed { false }; 73 74 // Cached version of the items in memory. 75 // If the value is too large to keep in memory, we store a null String. 76 mutable std::optional<HashMap<String, String>> m_items; 71 77 72 78 mutable std::unique_ptr<WebCore::SQLiteStatement> m_clearStatement;
Note:
See TracChangeset
for help on using the changeset viewer.