Diff
Modified: trunk/Source/WebCore/ChangeLog (179803 => 179804)
--- trunk/Source/WebCore/ChangeLog 2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebCore/ChangeLog 2015-02-08 22:06:06 UTC (rev 179804)
@@ -1,3 +1,15 @@
+2015-02-08 Chris Dumez <[email protected]>
+
+ [WK2] Add logging to validate the network cache efficacy (Part 1)
+ https://bugs.webkit.org/show_bug.cgi?id=141269
+ <rdar://problem/19632080>
+
+ Reviewed by Antti Koivisto.
+
+ Export an extra symbol.
+
+ * WebCore.exp.in:
+
2015-02-07 Chris Fleizach <[email protected]>
AX: The input element with type="search" has no default focus outline
Modified: trunk/Source/WebCore/WebCore.exp.in (179803 => 179804)
--- trunk/Source/WebCore/WebCore.exp.in 2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebCore/WebCore.exp.in 2015-02-08 22:06:06 UTC (rev 179804)
@@ -2262,6 +2262,7 @@
#endif
#if !ASSERT_DISABLED
+__ZN7WebCore21SQLiteDatabaseTracker24hasTransactionInProgressEv
__ZN7WebCore27NoExceptionAssertionCheckerC1EPKci
__ZN7WebCore27NoExceptionAssertionCheckerD1Ev
#endif
Modified: trunk/Source/WebKit2/ChangeLog (179803 => 179804)
--- trunk/Source/WebKit2/ChangeLog 2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/ChangeLog 2015-02-08 22:06:06 UTC (rev 179804)
@@ -1,3 +1,32 @@
+2015-02-08 Chris Dumez <[email protected]>
+
+ [WK2] Add logging to validate the network cache efficacy (Part 1)
+ https://bugs.webkit.org/show_bug.cgi?id=141269
+ <rdar://problem/19632080>
+
+ Reviewed by Antti Koivisto.
+
+ Add console logging to validate the network cache efficacy. This will
+ tell us if how the network cache satisties requests, in particular:
+ - Request cannot be handled by the cache
+ - Entry was not in the cache but is no longer there (pruned)
+ - Entry is in the cache but is not usable
+ - Entry is in the cache and is used.
+
+ This patch introduces a SQLite-based network cache statistics storage
+ that is used to store requests we have seen before, and query if we
+ have seen a request before. The storage is lightweight as it only
+ stores hashes in the database, in a background thread.
+
+ The statistics cache is initially bootstapped from the network disk
+ cache so that we have data initially and get as accurate statistics
+ as possible from the start.
+
+ To maintain an acceptable level of performance, we have a hard limit
+ on the number of unique requests that are retained set to 100000.
+
+ Diagnostic logging for this will be added in a follow-up patch.
+
2015-02-07 Chris Dumez <[email protected]>
Add Vector::removeFirstMatching() / removeAllMatching() methods taking lambda functions
Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp (179803 => 179804)
--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp 2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp 2015-02-08 22:06:06 UTC (rev 179804)
@@ -30,6 +30,7 @@
#include "Logging.h"
#include "NetworkCacheCoders.h"
+#include "NetworkCacheStatistics.h"
#include "NetworkCacheStorage.h"
#include "NetworkResourceLoader.h"
#include "WebCoreArgumentCoders.h"
@@ -49,10 +50,13 @@
return instance;
}
-bool NetworkCache::initialize(const String& cachePath)
+bool NetworkCache::initialize(const String& cachePath, bool enableEfficacyLogging)
{
m_storage = NetworkCacheStorage::open(cachePath);
+ if (enableEfficacyLogging)
+ m_statistics = NetworkCacheStatistics::open(cachePath);
+
LOG(NetworkCache, "(NetworkProcess) opened cache storage, success %d", !!m_storage);
return !!m_storage;
}
@@ -220,23 +224,33 @@
LOG(NetworkCache, "(NetworkProcess) retrieving %s priority %u", originalRequest.url().string().ascii().data(), originalRequest.priority());
+ NetworkCacheKey storageKey = makeCacheKey(originalRequest);
if (!canRetrieve(originalRequest)) {
+ if (m_statistics)
+ m_statistics->recordNotUsingCacheForRequest(storageKey, originalRequest);
+
completionHandler(nullptr);
return;
}
auto startTime = std::chrono::system_clock::now();
- NetworkCacheKey storageKey = makeCacheKey(originalRequest);
unsigned priority = originalRequest.priority();
- m_storage->retrieve(storageKey, priority, [this, originalRequest, completionHandler, startTime](std::unique_ptr<NetworkCacheStorage::Entry> entry) {
+ m_storage->retrieve(storageKey, priority, [this, originalRequest, completionHandler, startTime, storageKey](std::unique_ptr<NetworkCacheStorage::Entry> entry) {
if (!entry) {
LOG(NetworkCache, "(NetworkProcess) not found in storage");
+
+ if (m_statistics)
+ m_statistics->recordRetrievalFailure(storageKey, originalRequest);
+
completionHandler(nullptr);
return false;
}
auto decodedEntry = decodeStorageEntry(*entry, originalRequest);
bool success = !!decodedEntry;
+ if (m_statistics)
+ m_statistics->recordRetrievedCachedEntry(storageKey, originalRequest, success);
+
#if !LOG_DISABLED
auto elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - startTime).count();
#endif
@@ -331,8 +345,15 @@
LOG(NetworkCache, "(NetworkProcess) clearing cache");
if (m_storage)
m_storage->clear();
+ if (m_statistics)
+ m_statistics->clear();
}
+String NetworkCache::storagePath() const
+{
+ return m_storage ? m_storage->directoryPath() : String();
}
+}
+
#endif
Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h (179803 => 179804)
--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h 2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h 2015-02-08 22:06:06 UTC (rev 179804)
@@ -41,13 +41,15 @@
namespace WebKit {
+class NetworkCacheStatistics;
+
class NetworkCache {
WTF_MAKE_NONCOPYABLE(NetworkCache);
friend class WTF::NeverDestroyed<NetworkCache>;
public:
static NetworkCache& singleton();
- bool initialize(const String& cachePath);
+ bool initialize(const String& cachePath, bool enableEfficacyLogging);
void setMaximumSize(size_t);
bool isEnabled() const { return !!m_storage; }
@@ -75,11 +77,14 @@
void clear();
+ String storagePath() const;
+
private:
NetworkCache() = default;
~NetworkCache() = delete;
std::unique_ptr<NetworkCacheStorage> m_storage;
+ std::unique_ptr<NetworkCacheStatistics> m_statistics;
};
}
Added: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystemPosix.h (0 => 179804)
--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystemPosix.h (rev 0)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystemPosix.h 2015-02-08 22:06:06 UTC (rev 179804)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NetworkCacheFileSystemPosix_h
+#define NetworkCacheFileSystemPosix_h
+
+#if ENABLE(NETWORK_CACHE)
+
+#include "NetworkCacheKey.h"
+#include <WebCore/FileSystem.h>
+#include <dirent.h>
+#include <wtf/text/CString.h>
+
+namespace WebKit {
+
+template <typename Function>
+static void traverseDirectory(const String& path, uint8_t type, const Function& function)
+{
+ DIR* dir = opendir(WebCore::fileSystemRepresentation(path).data());
+ if (!dir)
+ return;
+ struct dirent* dp;
+ while ((dp = readdir(dir))) {
+ if (dp->d_type != type)
+ continue;
+ const char* name = dp->d_name;
+ if (!strcmp(name, ".") || !strcmp(name, ".."))
+ continue;
+ function(String(name));
+ }
+ closedir(dir);
+}
+
+inline void traverseCacheFiles(const String& cachePath, std::function<void (const String& fileName, const String& partitionPath)> function)
+{
+ traverseDirectory(cachePath, DT_DIR, [&cachePath, &function](const String& subdirName) {
+ String partitionPath = WebCore::pathByAppendingComponent(cachePath, subdirName);
+ traverseDirectory(partitionPath, DT_REG, [&function, &partitionPath](const String& fileName) {
+ if (fileName.length() != NetworkCacheKey::hashStringLength())
+ return;
+ function(fileName, partitionPath);
+ });
+ });
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(NETWORK_CACHE)
+
+#endif // NetworkCacheFileSystemPosix_h
+
Added: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.h (0 => 179804)
--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.h (rev 0)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.h 2015-02-08 22:06:06 UTC (rev 179804)
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NetworkCacheStatistics_h
+#define NetworkCacheStatistics_h
+
+#if ENABLE(NETWORK_CACHE)
+
+#include "NetworkCacheKey.h"
+#include "NetworkCacheStorage.h"
+#include <WebCore/SQLiteDatabase.h>
+
+namespace WebCore {
+class ResourceRequest;
+}
+
+namespace WebKit {
+
+class NetworkCacheStatistics {
+public:
+ static std::unique_ptr<NetworkCacheStatistics> open(const String& cachePath);
+
+ void clear();
+
+ void recordNotUsingCacheForRequest(const NetworkCacheKey&, const WebCore::ResourceRequest&);
+ void recordRetrievalFailure(const NetworkCacheKey&, const WebCore::ResourceRequest&);
+ void recordRetrievedCachedEntry(const NetworkCacheKey&, const WebCore::ResourceRequest&, bool success);
+
+private:
+ explicit NetworkCacheStatistics(const String& databasePath);
+
+ void initialize(const String& databasePath);
+ void bootstrapFromNetworkCache(const String& networkCachePath);
+ void shrinkIfNeeded();
+
+ void addHashToDatabase(const String& hash);
+
+ typedef std::function<void (bool wasEverRequested)> RequestedCompletionHandler;
+ void queryWasEverRequested(const String&, const RequestedCompletionHandler&);
+ void markAsRequested(const String& hash);
+
+ struct EverRequestedQuery {
+ String hash;
+ RequestedCompletionHandler completionHandler;
+ };
+
+ std::atomic<size_t> m_approximateEntryCount { 0 };
+
+#if PLATFORM(COCOA)
+ mutable DispatchPtr<dispatch_queue_t> m_backgroundIOQueue;
+#endif
+ mutable HashSet<std::unique_ptr<const EverRequestedQuery>> m_activeQueries;
+ WebCore::SQLiteDatabase m_database;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(NETWORK_CACHE)
+
+#endif // NetworkCacheStatistics_h
Added: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm (0 => 179804)
--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm (rev 0)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm 2015-02-08 22:06:06 UTC (rev 179804)
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(NETWORK_CACHE)
+#include "NetworkCacheStatistics.h"
+
+#include "Logging.h"
+#include "NetworkCache.h"
+#include "NetworkCacheFileSystemPosix.h"
+#include <WebCore/ResourceRequest.h>
+#include <WebCore/SQLiteDatabaseTracker.h>
+#include <WebCore/SQLiteStatement.h>
+#include <WebCore/SQLiteTransaction.h>
+#include <wtf/RunLoop.h>
+
+namespace WebKit {
+
+static const char* networkCacheStatisticsDatabaseName = "WebKitCacheStatistics.db";
+
+static bool executeSQLCommand(WebCore::SQLiteDatabase& database, const String& sql)
+{
+ ASSERT(!RunLoop::isMain());
+ ASSERT(WebCore::SQLiteDatabaseTracker::hasTransactionInProgress());
+ ASSERT(database.isOpen());
+
+ bool result = database.executeCommand(sql);
+ if (!result)
+ LOG_ERROR("Network cache statistics: failed to execute statement \"%s\" error \"%s\"", sql.utf8().data(), database.lastErrorMsg());
+
+ return result;
+}
+
+static bool executeSQLStatement(WebCore::SQLiteStatement& statement)
+{
+ ASSERT(!RunLoop::isMain());
+ ASSERT(WebCore::SQLiteDatabaseTracker::hasTransactionInProgress());
+ ASSERT(statement.database().isOpen());
+
+ bool result = statement.executeCommand();
+ if (!result)
+ LOG_ERROR("Network cache statistics: failed to execute statement \"%s\" error \"%s\"", statement.query().utf8().data(), statement.database().lastErrorMsg());
+
+ return result;
+}
+
+std::unique_ptr<NetworkCacheStatistics> NetworkCacheStatistics::open(const String& cachePath)
+{
+ ASSERT(RunLoop::isMain());
+
+ String databasePath = WebCore::pathByAppendingComponent(cachePath, networkCacheStatisticsDatabaseName);
+ return std::unique_ptr<NetworkCacheStatistics>(new NetworkCacheStatistics(databasePath));
+}
+
+NetworkCacheStatistics::NetworkCacheStatistics(const String& databasePath)
+ : m_backgroundIOQueue(adoptDispatch(dispatch_queue_create("com.apple.WebKit.Cache.Statistics.Background", DISPATCH_QUEUE_SERIAL)))
+{
+ dispatch_set_target_queue(m_backgroundIOQueue.get(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0));
+
+ initialize(databasePath);
+}
+
+void NetworkCacheStatistics::initialize(const String& databasePath)
+{
+ ASSERT(RunLoop::isMain());
+
+ auto startTime = std::chrono::system_clock::now();
+
+ StringCapture databasePathCapture(databasePath);
+ StringCapture networkCachePathCapture(NetworkCache::singleton().storagePath());
+ dispatch_async(m_backgroundIOQueue.get(), [this, databasePathCapture, networkCachePathCapture, startTime] {
+ WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter;
+
+ String databasePath = databasePathCapture.string();
+ if (!WebCore::makeAllDirectories(WebCore::directoryName(databasePath)))
+ return;
+
+ LOG(NetworkCache, "(NetworkProcess) Opening network cache statistics database at %s...", databasePath.utf8().data());
+ m_database.open(databasePath);
+ m_database.disableThreadingChecks();
+ if (!m_database.isOpen()) {
+ LOG_ERROR("Network cache statistics: Failed to open / create the network cache statistics database");
+ return;
+ }
+
+ executeSQLCommand(m_database, ASCIILiteral("CREATE TABLE IF NOT EXISTS AlreadyRequested (hash TEXT PRIMARY KEY)"));
+ WebCore::SQLiteStatement statement(m_database, ASCIILiteral("SELECT count(*) FROM AlreadyRequested"));
+ if (statement.prepareAndStep() != WebCore::SQLResultRow) {
+ LOG_ERROR("Network cache statistics: Failed to count the number of rows in AlreadyRequested table");
+ return;
+ }
+
+ m_approximateEntryCount = statement.getColumnInt(0);
+
+#if !LOG_DISABLED
+ auto elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - startTime).count();
+#endif
+ LOG(NetworkCache, "(NetworkProcess) Network cache statistics database load complete, entries=%lu time=%lldms", static_cast<size_t>(m_approximateEntryCount), elapsedMS);
+
+ if (!m_approximateEntryCount) {
+ bootstrapFromNetworkCache(networkCachePathCapture.string());
+#if !LOG_DISABLED
+ elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - startTime).count();
+#endif
+ LOG(NetworkCache, "(NetworkProcess) Network cache statistics database bootstrapping complete, entries=%lu time=%lldms", static_cast<size_t>(m_approximateEntryCount), elapsedMS);
+ }
+ });
+}
+
+void NetworkCacheStatistics::bootstrapFromNetworkCache(const String& networkCachePath)
+{
+ ASSERT(!RunLoop::isMain());
+
+ LOG(NetworkCache, "(NetworkProcess) Bootstrapping the network cache statistics database from the network cache...");
+
+ WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter;
+ WebCore::SQLiteTransaction bootstrapTransaction(m_database);
+ bootstrapTransaction.begin();
+
+ traverseCacheFiles(networkCachePath, [this](const String& hash, const String&) {
+ addHashToDatabase(hash);
+ });
+ bootstrapTransaction.commit();
+}
+
+void NetworkCacheStatistics::shrinkIfNeeded()
+{
+ ASSERT(RunLoop::isMain());
+ const size_t maxEntries = 100000;
+
+ if (m_approximateEntryCount < maxEntries)
+ return;
+
+ LOG(NetworkCache, "(NetworkProcess) shrinking statistics cache m_approximateEntryCount=%lu, maxEntries=%lu", static_cast<size_t>(m_approximateEntryCount), maxEntries);
+
+ clear();
+
+ StringCapture networkCachePathCapture(NetworkCache::singleton().storagePath());
+ dispatch_async(m_backgroundIOQueue.get(), [this, networkCachePathCapture] {
+ bootstrapFromNetworkCache(networkCachePathCapture.string());
+ LOG(NetworkCache, "(NetworkProcess) statistics cache shrink completed m_approximateEntryCount=%lu", static_cast<size_t>(m_approximateEntryCount));
+ });
+}
+
+void NetworkCacheStatistics::recordNotUsingCacheForRequest(const NetworkCacheKey& key, const WebCore::ResourceRequest& request)
+{
+ String hash = key.hashAsString();
+ WebCore::URL requestURL = request.url();
+ queryWasEverRequested(hash, [this, hash, requestURL](bool wasEverRequested) {
+ if (wasEverRequested) {
+ LOG(NetworkCache, "(NetworkProcess) %s was previously requested but is not handled by the cache", requestURL.string().ascii().data());
+ // FIXME: Do diagnostic logging.
+ } else
+ markAsRequested(hash);
+ });
+}
+
+void NetworkCacheStatistics::recordRetrievalFailure(const NetworkCacheKey& key, const WebCore::ResourceRequest& request)
+{
+ String hash = key.hashAsString();
+ WebCore::URL requestURL = request.url();
+ queryWasEverRequested(hash, [this, hash, requestURL](bool wasPreviouslyRequested) {
+ if (wasPreviouslyRequested) {
+ LOG(NetworkCache, "(NetworkProcess) %s was previously cached but is no longer in the cache", requestURL.string().ascii().data());
+ // FIXME: Do diagnostic logging.
+ } else
+ markAsRequested(hash);
+ });
+}
+
+void NetworkCacheStatistics::recordRetrievedCachedEntry(const NetworkCacheKey& key, const WebCore::ResourceRequest& request, bool success)
+{
+ WebCore::URL requestURL = request.url();
+ if (success)
+ LOG(NetworkCache, "(NetworkProcess) %s is in the cache and is used", requestURL.string().ascii().data());
+ else
+ LOG(NetworkCache, "(NetworkProcess) %s is in the cache but wasn't used", requestURL.string().ascii().data());
+ // FIXME: Do diagnostic logging.
+}
+
+void NetworkCacheStatistics::markAsRequested(const String& hash)
+{
+ ASSERT(RunLoop::isMain());
+
+ StringCapture hashCapture(hash);
+ dispatch_async(m_backgroundIOQueue.get(), [this, hashCapture] {
+ WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter;
+ if (m_database.isOpen())
+ addHashToDatabase(hashCapture.string());
+ });
+
+ shrinkIfNeeded();
+}
+
+void NetworkCacheStatistics::queryWasEverRequested(const String& hash, const RequestedCompletionHandler& completionHandler)
+{
+ ASSERT(RunLoop::isMain());
+
+ auto everRequestedQuery = std::make_unique<EverRequestedQuery>(EverRequestedQuery { hash, completionHandler });
+ auto& query = *everRequestedQuery;
+ m_activeQueries.add(WTF::move(everRequestedQuery));
+ dispatch_async(m_backgroundIOQueue.get(), [this, &query] {
+ WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter;
+ bool wasAlreadyRequested = false;
+ if (m_database.isOpen()) {
+ WebCore::SQLiteStatement statement(m_database, ASCIILiteral("SELECT hash FROM AlreadyRequested WHERE hash=?"));
+ if (statement.prepare() == WebCore::SQLResultOk) {
+ statement.bindText(1, query.hash);
+ wasAlreadyRequested = statement.step() == WebCore::SQLResultRow;
+ }
+ }
+ dispatch_async(dispatch_get_main_queue(), [this, &query, wasAlreadyRequested] {
+ query.completionHandler(wasAlreadyRequested);
+ m_activeQueries.remove(&query);
+ });
+ });
+}
+
+void NetworkCacheStatistics::clear()
+{
+ ASSERT(RunLoop::isMain());
+
+ dispatch_async(m_backgroundIOQueue.get(), [this] {
+ WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter;
+ if (m_database.isOpen()) {
+ executeSQLCommand(m_database, ASCIILiteral("DELETE FROM AlreadyRequested"));
+ m_approximateEntryCount = 0;
+ }
+ });
+}
+
+void NetworkCacheStatistics::addHashToDatabase(const String& hash)
+{
+ ASSERT(!RunLoop::isMain());
+ ASSERT(WebCore::SQLiteDatabaseTracker::hasTransactionInProgress());
+ ASSERT(m_database.isOpen());
+
+ WebCore::SQLiteStatement statement(m_database, ASCIILiteral("INSERT OR IGNORE INTO AlreadyRequested (hash) VALUES (?)"));
+ if (statement.prepare() != WebCore::SQLResultOk)
+ return;
+
+ statement.bindText(1, hash);
+ if (!executeSQLStatement(statement))
+ return;
+
+ ++m_approximateEntryCount;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(NETWORK_CACHE)
Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h (179803 => 179804)
--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h 2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h 2015-02-08 22:06:06 UTC (rev 179804)
@@ -155,6 +155,8 @@
static const unsigned version = 2;
+ const String& directoryPath() const { return m_directoryPath; }
+
private:
NetworkCacheStorage(const String& directoryPath);
Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm (179803 => 179804)
--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm 2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm 2015-02-08 22:06:06 UTC (rev 179804)
@@ -30,8 +30,7 @@
#include "Logging.h"
#include "NetworkCacheCoders.h"
-#include <WebCore/FileSystem.h>
-#include <dirent.h>
+#include "NetworkCacheFileSystemPosix.h"
#include <dispatch/dispatch.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -44,36 +43,6 @@
static const char networkCacheSubdirectory[] = "WebKitCache";
static const char versionDirectoryPrefix[] = "Version ";
-template <typename Function>
-static void traverseDirectory(const String& path, uint8_t type, const Function& function)
-{
- DIR* dir = opendir(WebCore::fileSystemRepresentation(path).data());
- if (!dir)
- return;
- struct dirent* dp;
- while ((dp = readdir(dir))) {
- if (dp->d_type != type)
- continue;
- const char* name = dp->d_name;
- if (!strcmp(name, ".") || !strcmp(name, ".."))
- continue;
- function(String(name));
- }
- closedir(dir);
-}
-
-static void traverseCacheFiles(const String& cachePath, std::function<void (const String& fileName, const String& partitionPath)> function)
-{
- traverseDirectory(cachePath, DT_DIR, [&cachePath, &function](const String& subdirName) {
- String partitionPath = WebCore::pathByAppendingComponent(cachePath, subdirName);
- traverseDirectory(partitionPath, DT_REG, [&function, &partitionPath](const String& fileName) {
- if (fileName.length() != NetworkCacheKey::hashStringLength())
- return;
- function(fileName, partitionPath);
- });
- });
-}
-
NetworkCacheStorage::Data::Data(const uint8_t* data, size_t size)
: m_dispatchData(adoptDispatch(dispatch_data_create(data, size, nullptr, DISPATCH_DATA_DESTRUCTOR_DEFAULT)))
, m_size(size)
Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkProcessCocoa.mm (179803 => 179804)
--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkProcessCocoa.mm 2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkProcessCocoa.mm 2015-02-08 22:06:06 UTC (rev 179804)
@@ -64,7 +64,7 @@
if (!m_diskCacheDirectory.isNull()) {
SandboxExtension::consumePermanently(parameters.diskCacheDirectoryExtensionHandle);
#if ENABLE(NETWORK_CACHE)
- if (parameters.shouldEnableNetworkCache && NetworkCache::singleton().initialize(m_diskCacheDirectory)) {
+ if (parameters.shouldEnableNetworkCache && NetworkCache::singleton().initialize(m_diskCacheDirectory, parameters.shouldEnableNetworkCacheEfficacyLogging)) {
RetainPtr<NSURLCache> urlCache(adoptNS([[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil]));
[NSURLCache setSharedURLCache:urlCache.get()];
return;
Modified: trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.cpp (179803 => 179804)
--- trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.cpp 2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.cpp 2015-02-08 22:06:06 UTC (rev 179804)
@@ -45,6 +45,7 @@
encoder << diskCacheDirectoryExtensionHandle;
#if ENABLE(NETWORK_CACHE)
encoder << shouldEnableNetworkCache;
+ encoder << shouldEnableNetworkCacheEfficacyLogging;
#endif
encoder << cookieStorageDirectory;
#if PLATFORM(IOS)
@@ -86,6 +87,8 @@
#if ENABLE(NETWORK_CACHE)
if (!decoder.decode(result.shouldEnableNetworkCache))
return false;
+ if (!decoder.decode(result.shouldEnableNetworkCacheEfficacyLogging))
+ return false;
#endif
if (!decoder.decode(result.cookieStorageDirectory))
return false;
Modified: trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.h (179803 => 179804)
--- trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.h 2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.h 2015-02-08 22:06:06 UTC (rev 179804)
@@ -58,6 +58,7 @@
SandboxExtension::Handle diskCacheDirectoryExtensionHandle;
#if ENABLE(NETWORK_CACHE)
bool shouldEnableNetworkCache;
+ bool shouldEnableNetworkCacheEfficacyLogging;
#endif
String cookieStorageDirectory;
Modified: trunk/Source/WebKit2/UIProcess/Cocoa/WebProcessPoolCocoa.mm (179803 => 179804)
--- trunk/Source/WebKit2/UIProcess/Cocoa/WebProcessPoolCocoa.mm 2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/WebProcessPoolCocoa.mm 2015-02-08 22:06:06 UTC (rev 179804)
@@ -81,6 +81,7 @@
#if ENABLE(NETWORK_CACHE)
static NSString * const WebKitNetworkCacheEnabledDefaultsKey = @"WebKitNetworkCacheEnabled";
+static NSString * const WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey = @"WebKitNetworkCacheEfficacyLoggingEnabled";
#endif
namespace WebKit {
@@ -106,6 +107,7 @@
#if ENABLE(NETWORK_CACHE)
[registrationDictionary setObject:[NSNumber numberWithBool:YES] forKey:WebKitNetworkCacheEnabledDefaultsKey];
+ [registrationDictionary setObject:[NSNumber numberWithBool:YES] forKey:WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey];
#endif
[[NSUserDefaults standardUserDefaults] registerDefaults:registrationDictionary];
@@ -252,6 +254,7 @@
#if ENABLE(NETWORK_CACHE)
parameters.shouldEnableNetworkCache = [[NSUserDefaults standardUserDefaults] boolForKey:WebKitNetworkCacheEnabledDefaultsKey];
+ parameters.shouldEnableNetworkCacheEfficacyLogging = [[NSUserDefaults standardUserDefaults] boolForKey:WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey];
#endif
}
#endif
Modified: trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj (179803 => 179804)
--- trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj 2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj 2015-02-08 22:06:06 UTC (rev 179804)
@@ -1147,6 +1147,9 @@
7CF47FFE17276AE3008ACB91 /* WKBundlePageBannerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7CF47FFC17276AE3008ACB91 /* WKBundlePageBannerMac.mm */; };
7CF47FFF17276AE3008ACB91 /* WKBundlePageBannerMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CF47FFD17276AE3008ACB91 /* WKBundlePageBannerMac.h */; settings = {ATTRIBUTES = (Private, ); }; };
7EC4F0FB18E4ACBB008056AF /* NetworkProcessCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7EC4F0F918E4A945008056AF /* NetworkProcessCocoa.mm */; };
+ 834B250F1A831A8D00CFB150 /* NetworkCacheFileSystemPosix.h in Headers */ = {isa = PBXBuildFile; fileRef = 834B250E1A831A8D00CFB150 /* NetworkCacheFileSystemPosix.h */; };
+ 834B25121A842C8700CFB150 /* NetworkCacheStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 834B25101A842C8700CFB150 /* NetworkCacheStatistics.h */; };
+ 834B25131A842C8700CFB150 /* NetworkCacheStatisticsCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 834B25111A842C8700CFB150 /* NetworkCacheStatisticsCocoa.mm */; };
8372DB251A674C8F00C697C5 /* WKPageDiagnosticLoggingClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 8372DB241A674C8F00C697C5 /* WKPageDiagnosticLoggingClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
8372DB281A67562800C697C5 /* WebPageDiagnosticLoggingClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8372DB261A67562800C697C5 /* WebPageDiagnosticLoggingClient.cpp */; };
8372DB291A67562800C697C5 /* WebPageDiagnosticLoggingClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 8372DB271A67562800C697C5 /* WebPageDiagnosticLoggingClient.h */; };
@@ -3321,6 +3324,9 @@
7CF47FFC17276AE3008ACB91 /* WKBundlePageBannerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKBundlePageBannerMac.mm; sourceTree = "<group>"; };
7CF47FFD17276AE3008ACB91 /* WKBundlePageBannerMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBundlePageBannerMac.h; sourceTree = "<group>"; };
7EC4F0F918E4A945008056AF /* NetworkProcessCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = NetworkProcessCocoa.mm; path = NetworkProcess/cocoa/NetworkProcessCocoa.mm; sourceTree = "<group>"; };
+ 834B250E1A831A8D00CFB150 /* NetworkCacheFileSystemPosix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheFileSystemPosix.h; sourceTree = "<group>"; };
+ 834B25101A842C8700CFB150 /* NetworkCacheStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheStatistics.h; sourceTree = "<group>"; };
+ 834B25111A842C8700CFB150 /* NetworkCacheStatisticsCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkCacheStatisticsCocoa.mm; sourceTree = "<group>"; };
8372DB241A674C8F00C697C5 /* WKPageDiagnosticLoggingClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKPageDiagnosticLoggingClient.h; sourceTree = "<group>"; };
8372DB261A67562800C697C5 /* WebPageDiagnosticLoggingClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageDiagnosticLoggingClient.cpp; sourceTree = "<group>"; };
8372DB271A67562800C697C5 /* WebPageDiagnosticLoggingClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageDiagnosticLoggingClient.h; sourceTree = "<group>"; };
@@ -7382,8 +7388,11 @@
E489D2871A0A2DB80078C06A /* NetworkCacheDecoder.h */,
E489D2881A0A2DB80078C06A /* NetworkCacheEncoder.cpp */,
E489D2891A0A2DB80078C06A /* NetworkCacheEncoder.h */,
+ 834B250E1A831A8D00CFB150 /* NetworkCacheFileSystemPosix.h */,
E4436EC01A0CFDB200EAD204 /* NetworkCacheKey.cpp */,
E4436EC11A0CFDB200EAD204 /* NetworkCacheKey.h */,
+ 834B25101A842C8700CFB150 /* NetworkCacheStatistics.h */,
+ 834B25111A842C8700CFB150 /* NetworkCacheStatisticsCocoa.mm */,
E4436EC21A0CFDB200EAD204 /* NetworkCacheStorage.h */,
E4436EC31A0CFDB200EAD204 /* NetworkCacheStorageCocoa.mm */,
);
@@ -7500,6 +7509,7 @@
1AC1336C18565C7A00F3EC05 /* APIPageHandle.h in Headers */,
1AFDD3151891B54000153970 /* APIPolicyClient.h in Headers */,
7CE4D2201A4914CA00C7F152 /* APIProcessPoolConfiguration.h in Headers */,
+ 834B25121A842C8700CFB150 /* NetworkCacheStatistics.h in Headers */,
F634445612A885C8000612D8 /* APISecurityOrigin.h in Headers */,
75A8D2E1187DEC1A00C39C9E /* APISession.h in Headers */,
1AFDE6621954E9B100C48FFA /* APISessionState.h in Headers */,
@@ -7686,6 +7696,7 @@
1A2161B011F37664008AD0F5 /* NPRuntimeObjectMap.h in Headers */,
1A2162B111F38971008AD0F5 /* NPRuntimeUtilities.h in Headers */,
1A2D84A3127F6AD1001EB962 /* NPVariantData.h in Headers */,
+ 834B250F1A831A8D00CFB150 /* NetworkCacheFileSystemPosix.h in Headers */,
BC8ACA1316670D89004C1941 /* ObjCObjectGraph.h in Headers */,
BCCF672D12C7EDF7008F9C35 /* OriginAndDatabases.h in Headers */,
7CF47FFB17275C57008ACB91 /* PageBanner.h in Headers */,
@@ -9885,6 +9896,7 @@
1C8E293A12761E5B00BC7BD0 /* WKInspector.cpp in Sources */,
0F3C725C196F605200AEDD0C /* WKInspectorHighlightView.mm in Sources */,
A54293A5195A43DD002782C7 /* WKInspectorNodeSearchGestureRecognizer.mm in Sources */,
+ 834B25131A842C8700CFB150 /* NetworkCacheStatisticsCocoa.mm in Sources */,
51A9E10A1315CD18009E7031 /* WKKeyValueStorageManager.cpp in Sources */,
33D3A3B51339600B00709BE4 /* WKMediaCacheManager.cpp in Sources */,
BC4075FD124FF0270068F20A /* WKMutableArray.cpp in Sources */,