Don't cache resources that are very unlikely to be reused
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 Mar 2015 21:09:14 +0000 (21:09 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 Mar 2015 21:09:14 +0000 (21:09 +0000)
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: https://svn.webkit.org/repository/webkit/trunk@182152 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/cache/disk-cache/disk-cache-request-max-stale-expected.txt
LayoutTests/http/tests/cache/disk-cache/disk-cache-request-max-stale.html
LayoutTests/http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy-expected.txt
LayoutTests/http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy.html
Source/WebCore/ChangeLog
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/FrameLoader.h
Source/WebCore/page/DiagnosticLoggingKeys.cpp
Source/WebCore/page/DiagnosticLoggingKeys.h
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl
Source/WebKit2/ChangeLog
Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp
Source/WebKit2/NetworkProcess/cache/NetworkCache.h
Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.cpp

index 686ac5b..1ce369f 100644 (file)
@@ -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
index aac0074..0fba14d 100644 (file)
@@ -5,23 +5,23 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 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 @@ response headers: {"Cache-control":"max-age=100"}
 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 @@ response headers: {"Cache-control":"max-age=100","Age":"200"}
 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 @@ response headers: {"Cache-control":"max-age=100"}
 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 @@ response headers: {"Cache-control":"max-age=100"}
 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 @@ response headers: {"Cache-control":"max-age=100","Age":"200"}
 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 @@ response headers: {"Cache-control":"max-age=100"}
 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"}
index 25d856a..f7ee12b 100644 (file)
@@ -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' } },
   ],
  [
index c0a5eb0..a5de237 100644 (file)
@@ -6,6 +6,170 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 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"}
index f9ec73f..570a40c 100644 (file)
@@ -36,7 +36,12 @@ var tests = generateTests(testMatrix);
 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>
index 1cd0b56..e7f3dad 100644 (file)
@@ -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
index 4e3a4f2..105c82c 100644 (file)
@@ -2561,6 +2561,8 @@ void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadTyp
 
     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 @@ void FrameLoader::forcePageTransitionIfNeeded()
     m_client.forcePageTransitionIfNeeded();
 }
 
+void FrameLoader::clearTestingOverrides()
+{
+    m_overrideCachePolicyForTesting = Nullopt;
+    m_overrideResourceLoadPriorityForTesting = Nullopt;
+}
+
 bool FrameLoaderClient::hasHTMLView() const
 {
     return true;
index 2c6748b..838a397 100644 (file)
@@ -290,7 +290,8 @@ public:
     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 @@ private:
     RefPtr<FrameNetworkingContext> m_networkingContext;
 
     Optional<ResourceRequestCachePolicy> m_overrideCachePolicyForTesting;
+    Optional<ResourceLoadPriority> m_overrideResourceLoadPriorityForTesting;
 
     URL m_previousURL;
     RefPtr<HistoryItem> m_requestedHistoryItem;
index 9ddd63c..18c79bd 100644 (file)
@@ -383,6 +383,11 @@ String DiagnosticLoggingKeys::uncacheableStatusCodeKey()
     return ASCIILiteral("uncacheableStatusCode");
 }
 
+String DiagnosticLoggingKeys::unlikelyToReuseKey()
+{
+    return ASCIILiteral("unlikelyToReuse");
+}
+
 String DiagnosticLoggingKeys::unsupportedHTTPMethodKey()
 {
     return ASCIILiteral("unsupportedHTTPMethod");
index cb86b4e..f9bc1cc 100644 (file)
@@ -108,6 +108,7 @@ public:
     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();
index 39f2f35..99401f6 100644 (file)
@@ -308,7 +308,7 @@ void Internals::resetToConsistentState(Page* page)
         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 @@ void Internals::setOverrideCachePolicy(const String& policy)
     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();
index 4e5dd55..71ff42e 100644 (file)
@@ -90,6 +90,7 @@ public:
     bool isLoadingFromMemoryCache(const String& url);
     String xhrResponseSource(XMLHttpRequest*);
     void setOverrideCachePolicy(const String&);
+    void setOverrideResourceLoadPriority(const String&);
 
     void clearMemoryCache();
     void pruneMemoryCacheToSize(unsigned size);
index 740eb2e..11884f0 100644 (file)
@@ -37,6 +37,13 @@ enum CachePolicy {
     "ReturnCacheDataDontLoad"
 };
 
+enum ResourceLoadPriority {
+    "ResourceLoadPriorityVeryLow",
+    "ResourceLoadPriorityLow",
+    "ResourceLoadPriorityMedium",
+    "ResourceLoadPriorityHigh",
+    "ResourceLoadPriorityVeryHigh"
+};
 
 [
     NoInterfaceObject,
@@ -56,6 +63,7 @@ enum CachePolicy {
     void pruneMemoryCacheToSize(long size);
     long memoryCacheSize();
     void setOverrideCachePolicy(CachePolicy policy);
+    void setOverrideResourceLoadPriority(ResourceLoadPriority priority);
 
     void clearPageCache();
     unsigned int pageCacheSize();
index cbda0b6..14e91b2 100644 (file)
@@ -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
index c4fa7d8..d8a6cf8 100644 (file)
@@ -182,12 +182,10 @@ static bool responseNeedsRevalidation(const WebCore::ResourceResponse& response,
     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 @@ static UseDecision canUse(const Entry& entry, const WebCore::ResourceRequest& re
     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,6 +214,81 @@ static RetrieveDecision canRetrieve(const WebCore::ResourceRequest& request)
     return RetrieveDecision::Yes;
 }
 
+// http://tools.ietf.org/html/rfc7231#page-48
+static bool isStatusCodeCacheableByDefault(int statusCode)
+{
+    switch (statusCode) {
+    case 200: // OK
+    case 203: // Non-Authoritative Information
+    case 204: // No Content
+    case 300: // Multiple Choices
+    case 301: // Moved Permanently
+    case 404: // Not Found
+    case 405: // Method Not Allowed
+    case 410: // Gone
+    case 414: // URI Too Long
+    case 501: // Not Implemented
+        return true;
+    default:
+        return false;
+    }
+}
+
+static bool isStatusCodePotentiallyCacheable(int statusCode)
+{
+    switch (statusCode) {
+    case 201: // Created
+    case 202: // Accepted
+    case 205: // Reset Content
+    case 302: // Found
+    case 303: // See Other
+    case 307: // Temporary redirect
+    case 403: // Forbidden
+    case 406: // Not Acceptable
+    case 415: // Unsupported Media Type
+        return true;
+    default:
+        return false;
+    }
+}
+
+static StoreDecision makeStoreDecision(const WebCore::ResourceRequest& originalRequest, const WebCore::ResourceResponse& response)
+{
+    if (!originalRequest.url().protocolIsInHTTPFamily() || !response.isHTTP())
+        return StoreDecision::NoDueToProtocol;
+
+    if (originalRequest.httpMethod() != "GET")
+        return StoreDecision::NoDueToHTTPMethod;
+
+    auto requestDirectives = WebCore::parseCacheControlDirectives(originalRequest.httpHeaderFields());
+    if (requestDirectives.noStore)
+        return StoreDecision::NoDueToNoStoreRequest;
+
+    if (response.cacheControlContainsNoStore())
+        return StoreDecision::NoDueToNoStoreResponse;
+
+    if (!isStatusCodeCacheableByDefault(response.httpStatusCode())) {
+        // http://tools.ietf.org/html/rfc7234#section-4.3.2
+        bool hasExpirationHeaders = std::isfinite(response.expires()) || std::isfinite(response.cacheControlMaxAge());
+        bool expirationHeadersAllowCaching = isStatusCodePotentiallyCacheable(response.httpStatusCode()) && hasExpirationHeaders;
+        if (!expirationHeadersAllowCaching)
+            return StoreDecision::NoDueToHTTPStatusCode;
+    }
+
+    // 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;
+
+        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());
@@ -229,7 +300,7 @@ void Cache::retrieve(const WebCore::ResourceRequest& originalRequest, uint64_t w
         m_statistics->recordRetrievalRequest(webPageID);
 
     Key storageKey = makeCacheKey(originalRequest);
-    RetrieveDecision retrieveDecision = canRetrieve(originalRequest);
+    auto retrieveDecision = makeRetrieveDecision(originalRequest);
     if (retrieveDecision != RetrieveDecision::Yes) {
         if (m_statistics)
             m_statistics->recordNotUsingCacheForRequest(webPageID, storageKey, originalRequest, retrieveDecision);
@@ -256,7 +327,7 @@ void Cache::retrieve(const WebCore::ResourceRequest& originalRequest, uint64_t w
 
         auto entry = Entry::decodeStorageRecord(*record);
 
-        auto useDecision = entry ? canUse(*entry, originalRequest) : UseDecision::NoDueToDecodeFailure;
+        auto useDecision = entry ? makeUseDecision(*entry, originalRequest) : UseDecision::NoDueToDecodeFailure;
         switch (useDecision) {
         case UseDecision::Use:
             break;
@@ -279,74 +350,6 @@ void Cache::retrieve(const WebCore::ResourceRequest& originalRequest, uint64_t w
     });
 }
 
-// http://tools.ietf.org/html/rfc7231#page-48
-static bool isStatusCodeCacheableByDefault(int statusCode)
-{
-    switch (statusCode) {
-    case 200: // OK
-    case 203: // Non-Authoritative Information
-    case 204: // No Content
-    case 300: // Multiple Choices
-    case 301: // Moved Permanently
-    case 404: // Not Found
-    case 405: // Method Not Allowed
-    case 410: // Gone
-    case 414: // URI Too Long
-    case 501: // Not Implemented
-        return true;
-    default:
-        return false;
-    }
-}
-
-static bool isStatusCodePotentiallyCacheable(int statusCode)
-{
-    switch (statusCode) {
-    case 201: // Created
-    case 202: // Accepted
-    case 205: // Reset Content
-    case 302: // Found
-    case 303: // See Other
-    case 307: // Temporary redirect
-    case 403: // Forbidden
-    case 406: // Not Acceptable
-    case 415: // Unsupported Media Type
-        return true;
-    default:
-        return false;
-    }
-}
-
-static StoreDecision canStore(const WebCore::ResourceRequest& originalRequest, const WebCore::ResourceResponse& response)
-{
-    if (!originalRequest.url().protocolIsInHTTPFamily() || !response.isHTTP())
-        return StoreDecision::NoDueToProtocol;
-
-    if (originalRequest.httpMethod() != "GET")
-        return StoreDecision::NoDueToHTTPMethod;
-
-    auto requestDirectives = WebCore::parseCacheControlDirectives(originalRequest.httpHeaderFields());
-    if (requestDirectives.noStore)
-        return StoreDecision::NoDueToNoStoreRequest;
-
-    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.
-        // http://tools.ietf.org/html/rfc7234#section-4.3.2
-        if (std::isfinite(response.expires()) || std::isfinite(response.cacheControlMaxAge()))
-            return StoreDecision::Yes;
-    }
-
-    LOG(NetworkCache, "(NetworkProcess) status code %d not cacheable by default and no explicit expiration headers", response.httpStatusCode());
-
-    return StoreDecision::NoDueToHTTPStatusCode;
-}
-
 void Cache::store(const WebCore::ResourceRequest& originalRequest, const WebCore::ResourceResponse& response, RefPtr<WebCore::SharedBuffer>&& responseData, std::function<void (MappedBody&)> completionHandler)
 {
     ASSERT(isEnabled());
@@ -354,7 +357,8 @@ void Cache::store(const WebCore::ResourceRequest& originalRequest, const WebCore
 
     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) {
index 402fbdf..5056b51 100644 (file)
@@ -62,14 +62,16 @@ enum class RetrieveDecision {
     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 {
index 12c8642..fa83219 100644 (file)
@@ -238,6 +238,8 @@ static String storeDecisionToDiagnosticKey(StoreDecision storeDecision)
         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();