Don't cache resources that are very unlikely to be reused
https://bugs.webkit.org/show_bug.cgi?id=143226
<rdar://problem/20347160>
Reviewed by Geoff Garen.
Source/WebCore:
Allow overriding resource load priorities via Internals for testing.
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::addExtraFieldsToRequest):
(WebCore::FrameLoader::clearTestingOverrides):
* loader/FrameLoader.h:
(WebCore::FrameLoader::setOverrideResourceLoadPriorityForTesting):
(WebCore::FrameLoader::clearOverrideCachePolicyForTesting): Deleted.
* page/DiagnosticLoggingKeys.cpp:
(WebCore::DiagnosticLoggingKeys::unlikelyToReuseKey):
* page/DiagnosticLoggingKeys.h:
Add a key.
* testing/Internals.cpp:
(WebCore::Internals::resetToConsistentState):
(WebCore::stringToResourceLoadPriority):
(WebCore::Internals::setOverrideResourceLoadPriority):
* testing/Internals.h:
* testing/Internals.idl:
Source/WebKit2:
We are writing lots of resources to the cache that are never used again.
In browse-around-randomly test this reduced number of cache entries created by ~20% and bytes written by ~5%.
* NetworkProcess/cache/NetworkCache.cpp:
(WebKit::NetworkCache::makeUseDecision):
(WebKit::NetworkCache::makeRetrieveDecision):
Rename for clarity.
(WebKit::NetworkCache::makeStoreDecision):
Store only if the resource has non-zero expiration or has validation headers.
Very High priority resources (main resources) keep the existing policy to minimize impact
on back navigation and tab restore.
(WebKit::NetworkCache::Cache::retrieve):
(WebKit::NetworkCache::Cache::store):
(WebKit::NetworkCache::canUse): Deleted.
(WebKit::NetworkCache::canRetrieve): Deleted.
(WebKit::NetworkCache::canStore): Deleted.
* NetworkProcess/cache/NetworkCache.h:
* NetworkProcess/cache/NetworkCacheStatistics.cpp:
(WebKit::NetworkCache::storeDecisionToDiagnosticKey):
LayoutTests:
* http/tests/cache/disk-cache/disk-cache-request-max-stale-expected.txt:
* http/tests/cache/disk-cache/disk-cache-request-max-stale-expected.html:
Keep max-age: 0 cacheable in this test by adding a validation header.
* http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy-expected.txt:
* http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy.html:
Rebase and expand to cover the high priority resource case.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@182152 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 686ac5b..1ce369f 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,21 @@
+2015-03-30 Antti Koivisto <antti@apple.com>
+
+ Don't cache resources that are very unlikely to be reused
+ https://bugs.webkit.org/show_bug.cgi?id=143226
+ <rdar://problem/20347160>
+
+ Reviewed by Geoff Garen.
+
+ * http/tests/cache/disk-cache/disk-cache-request-max-stale-expected.txt:
+ * http/tests/cache/disk-cache/disk-cache-request-max-stale-expected.html:
+
+ Keep max-age: 0 cacheable in this test by adding a validation header.
+
+ * http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy-expected.txt:
+ * http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy.html:
+
+ Rebase and expand to cover the high priority resource case.
+
2015-03-30 Marcos ChavarrÃa Teijeiro <chavarria1991@gmail.com>
Rebaseline accessibility/aria-toggle-button-with-title.html
diff --git a/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-max-stale-expected.txt b/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-max-stale-expected.txt
index aac0074..0fba14d 100644
--- a/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-max-stale-expected.txt
+++ b/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-max-stale-expected.txt
@@ -5,23 +5,23 @@
running 36 tests
-response headers: {"Cache-control":"max-age=0"}
+response headers: {"Cache-control":"max-age=0","ETag":"match"}
request headers: {"Cache-control":"max-stale=0"}
-response source: Network
+response source: Disk cache after validation
response headers: {"Cache-control":"max-age=100"}
request headers: {"Cache-control":"max-stale=0"}
response source: Disk cache
-response headers: {"Cache-control":"max-age=0","Age":"200"}
+response headers: {"Cache-control":"max-age=0","ETag":"match","Age":"200"}
request headers: {"Cache-control":"max-stale=0"}
-response source: Network
+response source: Disk cache after validation
response headers: {"Cache-control":"max-age=100","Age":"200"}
request headers: {"Cache-control":"max-stale=0"}
response source: Network
-response headers: {"Cache-control":"max-age=0"}
+response headers: {"Cache-control":"max-age=0","ETag":"match"}
request headers: {"Cache-control":"max-stale"}
response source: Disk cache
@@ -29,7 +29,7 @@
request headers: {"Cache-control":"max-stale"}
response source: Disk cache
-response headers: {"Cache-control":"max-age=0","Age":"200"}
+response headers: {"Cache-control":"max-age=0","ETag":"match","Age":"200"}
request headers: {"Cache-control":"max-stale"}
response source: Disk cache
@@ -37,7 +37,7 @@
request headers: {"Cache-control":"max-stale"}
response source: Disk cache
-response headers: {"Cache-control":"max-age=0"}
+response headers: {"Cache-control":"max-age=0","ETag":"match"}
request headers: {"Cache-control":"max-stale=100"}
response source: Disk cache
@@ -45,79 +45,79 @@
request headers: {"Cache-control":"max-stale=100"}
response source: Disk cache
-response headers: {"Cache-control":"max-age=0","Age":"200"}
+response headers: {"Cache-control":"max-age=0","ETag":"match","Age":"200"}
request headers: {"Cache-control":"max-stale=100"}
-response source: Network
+response source: Disk cache after validation
response headers: {"Cache-control":"max-age=100","Age":"200"}
request headers: {"Cache-control":"max-stale=100"}
response source: Network
-response headers: {"Cache-control":"max-age=0"}
+response headers: {"Cache-control":"max-age=0","ETag":"match"}
request headers: {"Cache-control":"max-stale=0, max-age=0"}
-response source: Network
+response source: Disk cache after validation
response headers: {"Cache-control":"max-age=100"}
request headers: {"Cache-control":"max-stale=0, max-age=0"}
response source: Network
-response headers: {"Cache-control":"max-age=0","Age":"200"}
+response headers: {"Cache-control":"max-age=0","ETag":"match","Age":"200"}
request headers: {"Cache-control":"max-stale=0, max-age=0"}
-response source: Network
+response source: Disk cache after validation
response headers: {"Cache-control":"max-age=100","Age":"200"}
request headers: {"Cache-control":"max-stale=0, max-age=0"}
response source: Network
-response headers: {"Cache-control":"max-age=0"}
+response headers: {"Cache-control":"max-age=0","ETag":"match"}
request headers: {"Cache-control":"max-stale, max-age=0"}
-response source: Network
+response source: Disk cache after validation
response headers: {"Cache-control":"max-age=100"}
request headers: {"Cache-control":"max-stale, max-age=0"}
response source: Network
-response headers: {"Cache-control":"max-age=0","Age":"200"}
+response headers: {"Cache-control":"max-age=0","ETag":"match","Age":"200"}
request headers: {"Cache-control":"max-stale, max-age=0"}
-response source: Network
+response source: Disk cache after validation
response headers: {"Cache-control":"max-age=100","Age":"200"}
request headers: {"Cache-control":"max-stale, max-age=0"}
response source: Network
-response headers: {"Cache-control":"max-age=0"}
+response headers: {"Cache-control":"max-age=0","ETag":"match"}
request headers: {"Cache-control":"max-stale=100, max-age=0"}
-response source: Network
+response source: Disk cache after validation
response headers: {"Cache-control":"max-age=100"}
request headers: {"Cache-control":"max-stale=100, max-age=0"}
response source: Network
-response headers: {"Cache-control":"max-age=0","Age":"200"}
+response headers: {"Cache-control":"max-age=0","ETag":"match","Age":"200"}
request headers: {"Cache-control":"max-stale=100, max-age=0"}
-response source: Network
+response source: Disk cache after validation
response headers: {"Cache-control":"max-age=100","Age":"200"}
request headers: {"Cache-control":"max-stale=100, max-age=0"}
response source: Network
-response headers: {"Cache-control":"max-age=0"}
+response headers: {"Cache-control":"max-age=0","ETag":"match"}
request headers: {"Cache-control":"max-stale=0, max-age=100"}
-response source: Network
+response source: Disk cache after validation
response headers: {"Cache-control":"max-age=100"}
request headers: {"Cache-control":"max-stale=0, max-age=100"}
response source: Disk cache
-response headers: {"Cache-control":"max-age=0","Age":"200"}
+response headers: {"Cache-control":"max-age=0","ETag":"match","Age":"200"}
request headers: {"Cache-control":"max-stale=0, max-age=100"}
-response source: Network
+response source: Disk cache after validation
response headers: {"Cache-control":"max-age=100","Age":"200"}
request headers: {"Cache-control":"max-stale=0, max-age=100"}
response source: Network
-response headers: {"Cache-control":"max-age=0"}
+response headers: {"Cache-control":"max-age=0","ETag":"match"}
request headers: {"Cache-control":"max-stale, max-age=100"}
response source: Disk cache
@@ -125,7 +125,7 @@
request headers: {"Cache-control":"max-stale, max-age=100"}
response source: Disk cache
-response headers: {"Cache-control":"max-age=0","Age":"200"}
+response headers: {"Cache-control":"max-age=0","ETag":"match","Age":"200"}
request headers: {"Cache-control":"max-stale, max-age=100"}
response source: Disk cache
@@ -133,7 +133,7 @@
request headers: {"Cache-control":"max-stale, max-age=100"}
response source: Disk cache
-response headers: {"Cache-control":"max-age=0"}
+response headers: {"Cache-control":"max-age=0","ETag":"match"}
request headers: {"Cache-control":"max-stale=100, max-age=100"}
response source: Disk cache
@@ -141,9 +141,9 @@
request headers: {"Cache-control":"max-stale=100, max-age=100"}
response source: Disk cache
-response headers: {"Cache-control":"max-age=0","Age":"200"}
+response headers: {"Cache-control":"max-age=0","ETag":"match","Age":"200"}
request headers: {"Cache-control":"max-stale=100, max-age=100"}
-response source: Network
+response source: Disk cache after validation
response headers: {"Cache-control":"max-age=100","Age":"200"}
request headers: {"Cache-control":"max-stale=100, max-age=100"}
diff --git a/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-max-stale.html b/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-max-stale.html
index 25d856a..f7ee12b 100644
--- a/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-max-stale.html
+++ b/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-max-stale.html
@@ -6,7 +6,7 @@
var testMatrix =
[
[
- { responseHeaders: {'Cache-control': 'max-age=0' } },
+ { responseHeaders: {'Cache-control': 'max-age=0', 'ETag': 'match' } },
{ responseHeaders: {'Cache-control': 'max-age=100' } },
],
[
diff --git a/LayoutTests/http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy-expected.txt b/LayoutTests/http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy-expected.txt
index c0a5eb0..a5de237 100644
--- a/LayoutTests/http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy-expected.txt
+++ b/LayoutTests/http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy-expected.txt
@@ -6,6 +6,170 @@
running 54 tests
response headers: undefined
+response source: Network
+
+response headers: {"Cache-control":"max-age=0"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100"}
+response source: Disk cache
+
+response headers: {"Cache-control":"no-store"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0, no-store"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100, no-store"}
+response source: Network
+
+response headers: {"Cache-control":"no-cache"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0, no-cache"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100, no-cache"}
+response source: Disk cache
+
+response headers: {"ETag":"match"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=0","ETag":"match"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=100","ETag":"match"}
+response source: Disk cache
+
+response headers: {"Cache-control":"no-store","ETag":"match"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0, no-store","ETag":"match"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100, no-store","ETag":"match"}
+response source: Network
+
+response headers: {"Cache-control":"no-cache","ETag":"match"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=0, no-cache","ETag":"match"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=100, no-cache","ETag":"match"}
+response source: Disk cache
+
+response headers: {"ETag":"nomatch"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=0","ETag":"nomatch"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=100","ETag":"nomatch"}
+response source: Disk cache
+
+response headers: {"Cache-control":"no-store","ETag":"nomatch"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0, no-store","ETag":"nomatch"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100, no-store","ETag":"nomatch"}
+response source: Network
+
+response headers: {"Cache-control":"no-cache","ETag":"nomatch"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=0, no-cache","ETag":"nomatch"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=100, no-cache","ETag":"nomatch"}
+response source: Disk cache
+
+response headers: {"Cache-control":"must-revalidate"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0, must-revalidate"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100, must-revalidate"}
+response source: Disk cache
+
+response headers: {"Cache-control":"no-store, must-revalidate"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0, no-store, must-revalidate"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100, no-store, must-revalidate"}
+response source: Network
+
+response headers: {"Cache-control":"no-cache, must-revalidate"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0, no-cache, must-revalidate"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100, no-cache, must-revalidate"}
+response source: Disk cache
+
+response headers: {"ETag":"match","Cache-control":"must-revalidate"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=0, must-revalidate","ETag":"match"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=100, must-revalidate","ETag":"match"}
+response source: Disk cache
+
+response headers: {"Cache-control":"no-store, must-revalidate","ETag":"match"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0, no-store, must-revalidate","ETag":"match"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100, no-store, must-revalidate","ETag":"match"}
+response source: Network
+
+response headers: {"Cache-control":"no-cache, must-revalidate","ETag":"match"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=0, no-cache, must-revalidate","ETag":"match"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=100, no-cache, must-revalidate","ETag":"match"}
+response source: Disk cache
+
+response headers: {"ETag":"nomatch","Cache-control":"must-revalidate"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=0, must-revalidate","ETag":"nomatch"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=100, must-revalidate","ETag":"nomatch"}
+response source: Disk cache
+
+response headers: {"Cache-control":"no-store, must-revalidate","ETag":"nomatch"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0, no-store, must-revalidate","ETag":"nomatch"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100, no-store, must-revalidate","ETag":"nomatch"}
+response source: Network
+
+response headers: {"Cache-control":"no-cache, must-revalidate","ETag":"nomatch"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=0, no-cache, must-revalidate","ETag":"nomatch"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=100, no-cache, must-revalidate","ETag":"nomatch"}
+response source: Disk cache
+
+Testing high priority resources
+
+response headers: undefined
response source: Disk cache
response headers: {"Cache-control":"max-age=0"}
diff --git a/LayoutTests/http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy.html b/LayoutTests/http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy.html
index f9ec73f..570a40c 100644
--- a/LayoutTests/http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy.html
+++ b/LayoutTests/http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy.html
@@ -36,7 +36,12 @@
debug("running " + tests.length + " tests");
debug("");
-runTests(tests);
+runTests(tests, function () {
+ debug("Testing high priority resources");
+ debug("");
+ internals.setOverrideResourceLoadPriority("ResourceLoadPriorityVeryHigh");
+ runTests(tests);
+});
</script>
<script src="/js-test-resources/js-test-post.js"></script>
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 1cd0b56..e7f3dad 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,32 @@
+2015-03-30 Antti Koivisto <antti@apple.com>
+
+ Don't cache resources that are very unlikely to be reused
+ https://bugs.webkit.org/show_bug.cgi?id=143226
+ <rdar://problem/20347160>
+
+ Reviewed by Geoff Garen.
+
+ Allow overriding resource load priorities via Internals for testing.
+
+ * loader/FrameLoader.cpp:
+ (WebCore::FrameLoader::addExtraFieldsToRequest):
+ (WebCore::FrameLoader::clearTestingOverrides):
+ * loader/FrameLoader.h:
+ (WebCore::FrameLoader::setOverrideResourceLoadPriorityForTesting):
+ (WebCore::FrameLoader::clearOverrideCachePolicyForTesting): Deleted.
+ * page/DiagnosticLoggingKeys.cpp:
+ (WebCore::DiagnosticLoggingKeys::unlikelyToReuseKey):
+ * page/DiagnosticLoggingKeys.h:
+
+ Add a key.
+
+ * testing/Internals.cpp:
+ (WebCore::Internals::resetToConsistentState):
+ (WebCore::stringToResourceLoadPriority):
+ (WebCore::Internals::setOverrideResourceLoadPriority):
+ * testing/Internals.h:
+ * testing/Internals.idl:
+
2015-03-30 Javier Fernandez <jfernandez@igalia.com>
[CSS Grid Layout] Upgrade align-self and align-items parsing to CSS 3
diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp
index 4e3a4f2..105c82c 100644
--- a/Source/WebCore/loader/FrameLoader.cpp
+++ b/Source/WebCore/loader/FrameLoader.cpp
@@ -2561,6 +2561,8 @@
if (m_overrideCachePolicyForTesting)
request.setCachePolicy(m_overrideCachePolicyForTesting.value());
+ if (m_overrideResourceLoadPriorityForTesting)
+ request.setPriority(m_overrideResourceLoadPriorityForTesting.value());
if (request.cachePolicy() == ReloadIgnoringCacheData) {
if (loadType == FrameLoadType::Reload)
@@ -3413,6 +3415,12 @@
m_client.forcePageTransitionIfNeeded();
}
+void FrameLoader::clearTestingOverrides()
+{
+ m_overrideCachePolicyForTesting = Nullopt;
+ m_overrideResourceLoadPriorityForTesting = Nullopt;
+}
+
bool FrameLoaderClient::hasHTMLView() const
{
return true;
diff --git a/Source/WebCore/loader/FrameLoader.h b/Source/WebCore/loader/FrameLoader.h
index 2c6748b..838a397 100644
--- a/Source/WebCore/loader/FrameLoader.h
+++ b/Source/WebCore/loader/FrameLoader.h
@@ -290,7 +290,8 @@
void forcePageTransitionIfNeeded();
void setOverrideCachePolicyForTesting(ResourceRequestCachePolicy policy) { m_overrideCachePolicyForTesting = policy; }
- void clearOverrideCachePolicyForTesting() { m_overrideCachePolicyForTesting = Nullopt; }
+ void setOverrideResourceLoadPriorityForTesting(ResourceLoadPriority priority) { m_overrideResourceLoadPriorityForTesting = priority; }
+ WEBCORE_EXPORT void clearTestingOverrides();
private:
enum FormSubmissionCacheLoadPolicy {
@@ -442,6 +443,7 @@
RefPtr<FrameNetworkingContext> m_networkingContext;
Optional<ResourceRequestCachePolicy> m_overrideCachePolicyForTesting;
+ Optional<ResourceLoadPriority> m_overrideResourceLoadPriorityForTesting;
URL m_previousURL;
RefPtr<HistoryItem> m_requestedHistoryItem;
diff --git a/Source/WebCore/page/DiagnosticLoggingKeys.cpp b/Source/WebCore/page/DiagnosticLoggingKeys.cpp
index 9ddd63c..18c79bd 100644
--- a/Source/WebCore/page/DiagnosticLoggingKeys.cpp
+++ b/Source/WebCore/page/DiagnosticLoggingKeys.cpp
@@ -383,6 +383,11 @@
return ASCIILiteral("uncacheableStatusCode");
}
+String DiagnosticLoggingKeys::unlikelyToReuseKey()
+{
+ return ASCIILiteral("unlikelyToReuse");
+}
+
String DiagnosticLoggingKeys::unsupportedHTTPMethodKey()
{
return ASCIILiteral("unsupportedHTTPMethod");
diff --git a/Source/WebCore/page/DiagnosticLoggingKeys.h b/Source/WebCore/page/DiagnosticLoggingKeys.h
index cb86b4e..f9bc1cc 100644
--- a/Source/WebCore/page/DiagnosticLoggingKeys.h
+++ b/Source/WebCore/page/DiagnosticLoggingKeys.h
@@ -108,6 +108,7 @@
static String styleSheetKey();
static String svgDocumentKey();
WEBCORE_EXPORT static String uncacheableStatusCodeKey();
+ WEBCORE_EXPORT static String unlikelyToReuseKey();
WEBCORE_EXPORT static String unsupportedHTTPMethodKey();
static String unsuspendableDOMObjectKey();
WEBCORE_EXPORT static String unusableCachedEntryKey();
diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp
index 39f2f35..99401f6 100644
--- a/Source/WebCore/testing/Internals.cpp
+++ b/Source/WebCore/testing/Internals.cpp
@@ -308,7 +308,7 @@
page->mainFrame().editor().toggleContinuousSpellChecking();
if (page->mainFrame().editor().isOverwriteModeEnabled())
page->mainFrame().editor().toggleOverwriteModeEnabled();
- page->mainFrame().loader().clearOverrideCachePolicyForTesting();
+ page->mainFrame().loader().clearTestingOverrides();
ApplicationCacheStorage::singleton().setDefaultOriginQuota(ApplicationCacheStorage::noQuota());
#if ENABLE(VIDEO)
MediaSessionManager::sharedManager().resetRestrictions();
@@ -445,6 +445,27 @@
frame()->loader().setOverrideCachePolicyForTesting(stringToResourceRequestCachePolicy(policy));
}
+static ResourceLoadPriority stringToResourceLoadPriority(const String& policy)
+{
+ if (policy == "ResourceLoadPriorityVeryLow")
+ return ResourceLoadPriorityVeryLow;
+ if (policy == "ResourceLoadPriorityLow")
+ return ResourceLoadPriorityLow;
+ if (policy == "ResourceLoadPriorityMedium")
+ return ResourceLoadPriorityMedium;
+ if (policy == "ResourceLoadPriorityHigh")
+ return ResourceLoadPriorityHigh;
+ if (policy == "ResourceLoadPriorityVeryHigh")
+ return ResourceLoadPriorityVeryHigh;
+ ASSERT_NOT_REACHED();
+ return ResourceLoadPriorityLow;
+}
+
+void Internals::setOverrideResourceLoadPriority(const String& priority)
+{
+ frame()->loader().setOverrideResourceLoadPriorityForTesting(stringToResourceLoadPriority(priority));
+}
+
void Internals::clearMemoryCache()
{
MemoryCache::singleton().evictResources();
diff --git a/Source/WebCore/testing/Internals.h b/Source/WebCore/testing/Internals.h
index 4e5dd55..71ff42e3 100644
--- a/Source/WebCore/testing/Internals.h
+++ b/Source/WebCore/testing/Internals.h
@@ -90,6 +90,7 @@
bool isLoadingFromMemoryCache(const String& url);
String xhrResponseSource(XMLHttpRequest*);
void setOverrideCachePolicy(const String&);
+ void setOverrideResourceLoadPriority(const String&);
void clearMemoryCache();
void pruneMemoryCacheToSize(unsigned size);
diff --git a/Source/WebCore/testing/Internals.idl b/Source/WebCore/testing/Internals.idl
index 740eb2e..11884f0 100644
--- a/Source/WebCore/testing/Internals.idl
+++ b/Source/WebCore/testing/Internals.idl
@@ -37,6 +37,13 @@
"ReturnCacheDataDontLoad"
};
+enum ResourceLoadPriority {
+ "ResourceLoadPriorityVeryLow",
+ "ResourceLoadPriorityLow",
+ "ResourceLoadPriorityMedium",
+ "ResourceLoadPriorityHigh",
+ "ResourceLoadPriorityVeryHigh"
+};
[
NoInterfaceObject,
@@ -56,6 +63,7 @@
void pruneMemoryCacheToSize(long size);
long memoryCacheSize();
void setOverrideCachePolicy(CachePolicy policy);
+ void setOverrideResourceLoadPriority(ResourceLoadPriority priority);
void clearPageCache();
unsigned int pageCacheSize();
diff --git a/Source/WebKit2/ChangeLog b/Source/WebKit2/ChangeLog
index cbda0b6..14e91b2 100644
--- a/Source/WebKit2/ChangeLog
+++ b/Source/WebKit2/ChangeLog
@@ -1,3 +1,37 @@
+2015-03-30 Antti Koivisto <antti@apple.com>
+
+ Don't cache resources that are very unlikely to be reused
+ https://bugs.webkit.org/show_bug.cgi?id=143226
+ <rdar://problem/20347160>
+
+ Reviewed by Geoff Garen.
+
+ We are writing lots of resources to the cache that are never used again.
+
+ In browse-around-randomly test this reduced number of cache entries created by ~20% and bytes written by ~5%.
+
+ * NetworkProcess/cache/NetworkCache.cpp:
+ (WebKit::NetworkCache::makeUseDecision):
+ (WebKit::NetworkCache::makeRetrieveDecision):
+
+ Rename for clarity.
+
+ (WebKit::NetworkCache::makeStoreDecision):
+
+ Store only if the resource has non-zero expiration or has validation headers.
+
+ Very High priority resources (main resources) keep the existing policy to minimize impact
+ on back navigation and tab restore.
+
+ (WebKit::NetworkCache::Cache::retrieve):
+ (WebKit::NetworkCache::Cache::store):
+ (WebKit::NetworkCache::canUse): Deleted.
+ (WebKit::NetworkCache::canRetrieve): Deleted.
+ (WebKit::NetworkCache::canStore): Deleted.
+ * NetworkProcess/cache/NetworkCache.h:
+ * NetworkProcess/cache/NetworkCacheStatistics.cpp:
+ (WebKit::NetworkCache::storeDecisionToDiagnosticKey):
+
2015-03-30 Tim Horton <timothy_horton@apple.com>
Swipe snapshot removed too early (jumps around) on arstechnica and NYT
diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp
index c4fa7d8..d8a6cf8 100644
--- a/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp
+++ b/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp
@@ -182,12 +182,10 @@
return responseHasExpired(response, timestamp, requestDirectives.maxStale);
}
-static UseDecision canUse(const Entry& entry, const WebCore::ResourceRequest& request)
+static UseDecision makeUseDecision(const Entry& entry, const WebCore::ResourceRequest& request)
{
- if (!verifyVaryingRequestHeaders(entry.varyingRequestHeaders(), request)) {
- LOG(NetworkCache, "(NetworkProcess) varying header mismatch\n");
+ if (!verifyVaryingRequestHeaders(entry.varyingRequestHeaders(), request))
return UseDecision::NoDueToVaryingHeaderMismatch;
- }
// We never revalidate in the case of a history navigation.
if (cachePolicyAllowsExpired(request.cachePolicy()))
@@ -196,15 +194,13 @@
if (!responseNeedsRevalidation(entry.response(), request, entry.timeStamp()))
return UseDecision::Use;
- bool hasValidatorFields = entry.response().hasCacheValidatorFields();
- LOG(NetworkCache, "(NetworkProcess) needsRevalidation hasValidatorFields=%d", hasValidatorFields);
- if (!hasValidatorFields)
+ if (!entry.response().hasCacheValidatorFields())
return UseDecision::NoDueToMissingValidatorFields;
return UseDecision::Validate;
}
-static RetrieveDecision canRetrieve(const WebCore::ResourceRequest& request)
+static RetrieveDecision makeRetrieveDecision(const WebCore::ResourceRequest& request)
{
// FIXME: Support HEAD requests.
if (request.httpMethod() != "GET")
@@ -218,67 +214,6 @@
return RetrieveDecision::Yes;
}
-void Cache::retrieve(const WebCore::ResourceRequest& originalRequest, uint64_t webPageID, std::function<void (std::unique_ptr<Entry>)> completionHandler)
-{
- ASSERT(isEnabled());
- ASSERT(originalRequest.url().protocolIsInHTTPFamily());
-
- LOG(NetworkCache, "(NetworkProcess) retrieving %s priority %u", originalRequest.url().string().ascii().data(), originalRequest.priority());
-
- if (m_statistics)
- m_statistics->recordRetrievalRequest(webPageID);
-
- Key storageKey = makeCacheKey(originalRequest);
- RetrieveDecision retrieveDecision = canRetrieve(originalRequest);
- if (retrieveDecision != RetrieveDecision::Yes) {
- if (m_statistics)
- m_statistics->recordNotUsingCacheForRequest(webPageID, storageKey, originalRequest, retrieveDecision);
-
- completionHandler(nullptr);
- return;
- }
-
- auto startTime = std::chrono::system_clock::now();
- unsigned priority = originalRequest.priority();
-
- m_storage->retrieve(storageKey, priority, [this, originalRequest, completionHandler, startTime, storageKey, webPageID](std::unique_ptr<Storage::Record> record) {
- if (!record) {
- LOG(NetworkCache, "(NetworkProcess) not found in storage");
-
- if (m_statistics)
- m_statistics->recordRetrievalFailure(webPageID, storageKey, originalRequest);
-
- completionHandler(nullptr);
- return false;
- }
-
- ASSERT(record->key == storageKey);
-
- auto entry = Entry::decodeStorageRecord(*record);
-
- auto useDecision = entry ? canUse(*entry, originalRequest) : UseDecision::NoDueToDecodeFailure;
- switch (useDecision) {
- case UseDecision::Use:
- break;
- case UseDecision::Validate:
- entry->setNeedsValidation();
- break;
- default:
- entry = nullptr;
- };
-
-#if !LOG_DISABLED
- auto elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - startTime).count();
- LOG(NetworkCache, "(NetworkProcess) retrieve complete useDecision=%d priority=%u time=%lldms", useDecision, originalRequest.priority(), elapsedMS);
-#endif
- completionHandler(WTF::move(entry));
-
- if (m_statistics)
- m_statistics->recordRetrievedCachedEntry(webPageID, storageKey, originalRequest, useDecision);
- return useDecision != UseDecision::NoDueToDecodeFailure;
- });
-}
-
// http://tools.ietf.org/html/rfc7231#page-48
static bool isStatusCodeCacheableByDefault(int statusCode)
{
@@ -317,7 +252,7 @@
}
}
-static StoreDecision canStore(const WebCore::ResourceRequest& originalRequest, const WebCore::ResourceResponse& response)
+static StoreDecision makeStoreDecision(const WebCore::ResourceRequest& originalRequest, const WebCore::ResourceResponse& response)
{
if (!originalRequest.url().protocolIsInHTTPFamily() || !response.isHTTP())
return StoreDecision::NoDueToProtocol;
@@ -332,19 +267,87 @@
if (response.cacheControlContainsNoStore())
return StoreDecision::NoDueToNoStoreResponse;
- if (isStatusCodeCacheableByDefault(response.httpStatusCode()))
- return StoreDecision::Yes;
-
- if (isStatusCodePotentiallyCacheable(response.httpStatusCode())) {
- // Check for expiration headers allowing us to cache.
+ if (!isStatusCodeCacheableByDefault(response.httpStatusCode())) {
// http://tools.ietf.org/html/rfc7234#section-4.3.2
- if (std::isfinite(response.expires()) || std::isfinite(response.cacheControlMaxAge()))
- return StoreDecision::Yes;
+ bool hasExpirationHeaders = std::isfinite(response.expires()) || std::isfinite(response.cacheControlMaxAge());
+ bool expirationHeadersAllowCaching = isStatusCodePotentiallyCacheable(response.httpStatusCode()) && hasExpirationHeaders;
+ if (!expirationHeadersAllowCaching)
+ return StoreDecision::NoDueToHTTPStatusCode;
}
- LOG(NetworkCache, "(NetworkProcess) status code %d not cacheable by default and no explicit expiration headers", response.httpStatusCode());
+ // Main resource has ResourceLoadPriorityVeryHigh.
+ bool storeUnconditionallyForHistoryNavigation = originalRequest.priority() == WebCore::ResourceLoadPriorityVeryHigh;
+ if (!storeUnconditionallyForHistoryNavigation) {
+ auto currentTime = std::chrono::duration<double>(std::chrono::system_clock::now().time_since_epoch());
+ bool hasNonZeroLifetime = WebCore::computeFreshnessLifetimeForHTTPFamily(response, currentTime.count()) > 0;
- return StoreDecision::NoDueToHTTPStatusCode;
+ bool possiblyReusable = response.hasCacheValidatorFields() || hasNonZeroLifetime;
+ if (!possiblyReusable)
+ return StoreDecision::NoDueToUnlikelyToReuse;
+ }
+
+ return StoreDecision::Yes;
+}
+
+void Cache::retrieve(const WebCore::ResourceRequest& originalRequest, uint64_t webPageID, std::function<void (std::unique_ptr<Entry>)> completionHandler)
+{
+ ASSERT(isEnabled());
+ ASSERT(originalRequest.url().protocolIsInHTTPFamily());
+
+ LOG(NetworkCache, "(NetworkProcess) retrieving %s priority %u", originalRequest.url().string().ascii().data(), originalRequest.priority());
+
+ if (m_statistics)
+ m_statistics->recordRetrievalRequest(webPageID);
+
+ Key storageKey = makeCacheKey(originalRequest);
+ auto retrieveDecision = makeRetrieveDecision(originalRequest);
+ if (retrieveDecision != RetrieveDecision::Yes) {
+ if (m_statistics)
+ m_statistics->recordNotUsingCacheForRequest(webPageID, storageKey, originalRequest, retrieveDecision);
+
+ completionHandler(nullptr);
+ return;
+ }
+
+ auto startTime = std::chrono::system_clock::now();
+ unsigned priority = originalRequest.priority();
+
+ m_storage->retrieve(storageKey, priority, [this, originalRequest, completionHandler, startTime, storageKey, webPageID](std::unique_ptr<Storage::Record> record) {
+ if (!record) {
+ LOG(NetworkCache, "(NetworkProcess) not found in storage");
+
+ if (m_statistics)
+ m_statistics->recordRetrievalFailure(webPageID, storageKey, originalRequest);
+
+ completionHandler(nullptr);
+ return false;
+ }
+
+ ASSERT(record->key == storageKey);
+
+ auto entry = Entry::decodeStorageRecord(*record);
+
+ auto useDecision = entry ? makeUseDecision(*entry, originalRequest) : UseDecision::NoDueToDecodeFailure;
+ switch (useDecision) {
+ case UseDecision::Use:
+ break;
+ case UseDecision::Validate:
+ entry->setNeedsValidation();
+ break;
+ default:
+ entry = nullptr;
+ };
+
+#if !LOG_DISABLED
+ auto elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - startTime).count();
+ LOG(NetworkCache, "(NetworkProcess) retrieve complete useDecision=%d priority=%u time=%lldms", useDecision, originalRequest.priority(), elapsedMS);
+#endif
+ completionHandler(WTF::move(entry));
+
+ if (m_statistics)
+ m_statistics->recordRetrievedCachedEntry(webPageID, storageKey, originalRequest, useDecision);
+ return useDecision != UseDecision::NoDueToDecodeFailure;
+ });
}
void Cache::store(const WebCore::ResourceRequest& originalRequest, const WebCore::ResourceResponse& response, RefPtr<WebCore::SharedBuffer>&& responseData, std::function<void (MappedBody&)> completionHandler)
@@ -354,7 +357,8 @@
LOG(NetworkCache, "(NetworkProcess) storing %s, partition %s", originalRequest.url().string().latin1().data(), originalRequest.cachePartition().latin1().data());
- StoreDecision storeDecision = canStore(originalRequest, response);
+ StoreDecision storeDecision = makeStoreDecision(originalRequest, response);
+
if (storeDecision != StoreDecision::Yes) {
LOG(NetworkCache, "(NetworkProcess) didn't store, storeDecision=%d", storeDecision);
if (m_statistics) {
diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCache.h b/Source/WebKit2/NetworkProcess/cache/NetworkCache.h
index 402fbdf..5056b51 100644
--- a/Source/WebKit2/NetworkProcess/cache/NetworkCache.h
+++ b/Source/WebKit2/NetworkProcess/cache/NetworkCache.h
@@ -62,14 +62,16 @@
NoDueToReloadIgnoringCache
};
+// FIXME: This enum is used in the Statistics code in a way that prevents removing or reordering anything.
enum class StoreDecision {
Yes,
NoDueToProtocol,
NoDueToHTTPMethod,
- NoDueToAttachmentResponse,
+ NoDueToAttachmentResponse, // Unused.
NoDueToNoStoreResponse,
NoDueToHTTPStatusCode,
- NoDueToNoStoreRequest
+ NoDueToNoStoreRequest,
+ NoDueToUnlikelyToReuse
};
enum class UseDecision {
diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.cpp
index 12c8642..fa83219 100644
--- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.cpp
+++ b/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.cpp
@@ -238,6 +238,8 @@
return WebCore::DiagnosticLoggingKeys::cacheControlNoStoreKey();
case StoreDecision::NoDueToHTTPStatusCode:
return WebCore::DiagnosticLoggingKeys::uncacheableStatusCodeKey();
+ case StoreDecision::NoDueToUnlikelyToReuse:
+ return WebCore::DiagnosticLoggingKeys::unlikelyToReuseKey();
case StoreDecision::Yes:
// It was stored but could not be retrieved so it must have been pruned from the cache.
return WebCore::DiagnosticLoggingKeys::noLongerInCacheKey();