Title: [187958] trunk/Source/WebKit2
Revision
187958
Author
an...@apple.com
Date
2015-08-05 03:27:18 -0700 (Wed, 05 Aug 2015)

Log Message

Network cache fetches should have timeout
https://bugs.webkit.org/show_bug.cgi?id=147631

Reviewed by Andreas Kling.

System might be under heavy I/O pressure. If it takes long time to get data from disk we should load from network instead.

This patch introduces 1.5s timeout for disk reads. If the last dispatched cache read takes longer than that we cancel all
active and pending reads and just load those resources from network.

* NetworkProcess/cache/NetworkCacheStorage.cpp:
(WebKit::NetworkCache::Storage::ReadOperation::ReadOperation):
(WebKit::NetworkCache::Storage::ReadOperation::cancel):
(WebKit::NetworkCache::Storage::ReadOperation::finish):

    Factor to functions.

(WebKit::NetworkCache::Storage::Storage):
(WebKit::NetworkCache::Storage::updateFileModificationTime):
(WebKit::NetworkCache::Storage::dispatchReadOperation):
(WebKit::NetworkCache::Storage::finishReadOperation):
(WebKit::NetworkCache::Storage::cancelAllReadOperations):
(WebKit::NetworkCache::Storage::dispatchPendingReadOperations):
(WebKit::NetworkCache::Storage::dispatchPendingWriteOperations):

    Also make dispatch functions transfer the operation ownership.

(WebKit::NetworkCache::shouldStoreBodyAsBlob):
(WebKit::NetworkCache::Storage::dispatchWriteOperation):
* NetworkProcess/cache/NetworkCacheStorage.h:

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (187957 => 187958)


--- trunk/Source/WebKit2/ChangeLog	2015-08-05 10:25:41 UTC (rev 187957)
+++ trunk/Source/WebKit2/ChangeLog	2015-08-05 10:27:18 UTC (rev 187958)
@@ -1,3 +1,36 @@
+2015-08-04  Antti Koivisto  <an...@apple.com>
+
+        Network cache fetches should have timeout
+        https://bugs.webkit.org/show_bug.cgi?id=147631
+
+        Reviewed by Andreas Kling.
+
+        System might be under heavy I/O pressure. If it takes long time to get data from disk we should load from network instead.
+
+        This patch introduces 1.5s timeout for disk reads. If the last dispatched cache read takes longer than that we cancel all
+        active and pending reads and just load those resources from network.
+
+        * NetworkProcess/cache/NetworkCacheStorage.cpp:
+        (WebKit::NetworkCache::Storage::ReadOperation::ReadOperation):
+        (WebKit::NetworkCache::Storage::ReadOperation::cancel):
+        (WebKit::NetworkCache::Storage::ReadOperation::finish):
+
+            Factor to functions.
+
+        (WebKit::NetworkCache::Storage::Storage):
+        (WebKit::NetworkCache::Storage::updateFileModificationTime):
+        (WebKit::NetworkCache::Storage::dispatchReadOperation):
+        (WebKit::NetworkCache::Storage::finishReadOperation):
+        (WebKit::NetworkCache::Storage::cancelAllReadOperations):
+        (WebKit::NetworkCache::Storage::dispatchPendingReadOperations):
+        (WebKit::NetworkCache::Storage::dispatchPendingWriteOperations):
+
+            Also make dispatch functions transfer the operation ownership.
+
+        (WebKit::NetworkCache::shouldStoreBodyAsBlob):
+        (WebKit::NetworkCache::Storage::dispatchWriteOperation):
+        * NetworkProcess/cache/NetworkCacheStorage.h:
+
 2015-08-04  Matt Rajca  <mra...@apple.com>
 
         Media Session: add a focus manager that WebKit clients can use to access the focused media element

Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp (187957 => 187958)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp	2015-08-05 10:25:41 UTC (rev 187957)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp	2015-08-05 10:27:18 UTC (rev 187958)
@@ -56,6 +56,9 @@
         , completionHandler(completionHandler)
     { }
 
+    void cancel();
+    bool finish();
+
     const Key key;
     const RetrieveCompletionHandler completionHandler;
     
@@ -63,8 +66,34 @@
     SHA1::Digest expectedBodyHash;
     BlobStorage::Blob resultBodyBlob;
     std::atomic<unsigned> activeCount { 0 };
+    bool isCanceled { false };
 };
 
+void Storage::ReadOperation::cancel()
+{
+    ASSERT(RunLoop::isMain());
+
+    if (isCanceled)
+        return;
+    isCanceled = true;
+    completionHandler(nullptr);
+}
+
+bool Storage::ReadOperation::finish()
+{
+    ASSERT(RunLoop::isMain());
+
+    if (isCanceled)
+        return false;
+    if (resultRecord && resultRecord->body.isNull()) {
+        if (resultBodyBlob.hash == expectedBodyHash)
+            resultRecord->body = resultBodyBlob.data;
+        else
+            resultRecord = nullptr;
+    }
+    return completionHandler(WTF::move(resultRecord));
+}
+
 struct Storage::WriteOperation {
     WTF_MAKE_FAST_ALLOCATED;
 public:
@@ -147,6 +176,7 @@
 Storage::Storage(const String& baseDirectoryPath)
     : m_basePath(baseDirectoryPath)
     , m_recordsPath(makeRecordsDirectoryPath(baseDirectoryPath))
+    , m_readOperationTimeoutTimer(*this, &Storage::cancelAllReadOperations)
     , m_writeOperationDispatchTimer(*this, &Storage::dispatchPendingWriteOperations)
     , m_ioQueue(WorkQueue::create("com.apple.WebKit.Cache.Storage", WorkQueue::Type::Concurrent))
     , m_backgroundIOQueue(WorkQueue::create("com.apple.WebKit.Cache.Storage.background", WorkQueue::Type::Concurrent, WorkQueue::QOS::Background))
@@ -486,11 +516,17 @@
     });
 }
 
-void Storage::dispatchReadOperation(ReadOperation& readOperation)
+void Storage::dispatchReadOperation(std::unique_ptr<ReadOperation> readOperationPtr)
 {
     ASSERT(RunLoop::isMain());
-    ASSERT(m_activeReadOperations.contains(&readOperation));
 
+    auto& readOperation = *readOperationPtr;
+    m_activeReadOperations.add(WTF::move(readOperationPtr));
+
+    // I/O pressure may make disk operations slow. If they start taking very long time we rather go to network.
+    const auto readTimeout = 1500_ms;
+    m_readOperationTimeoutTimer.startOneShot(readTimeout);
+
     bool shouldGetBodyBlob = !m_bodyFilter || m_bodyFilter->mayContain(readOperation.key.hash());
 
     ioQueue().dispatch([this, &readOperation, shouldGetBodyBlob] {
@@ -524,26 +560,43 @@
         return;
 
     RunLoop::main().dispatch([this, &readOperation] {
-        if (readOperation.resultRecord && readOperation.resultRecord->body.isNull()) {
-            if (readOperation.resultBodyBlob.hash == readOperation.expectedBodyHash)
-                readOperation.resultRecord->body = readOperation.resultBodyBlob.data;
-            else
-                readOperation.resultRecord = nullptr;
-        }
-
-        bool success = readOperation.completionHandler(WTF::move(readOperation.resultRecord));
+        bool success = readOperation.finish();
         if (success)
             updateFileModificationTime(recordPathForKey(readOperation.key));
-        else
+        else if (!readOperation.isCanceled)
             remove(readOperation.key);
+
         ASSERT(m_activeReadOperations.contains(&readOperation));
         m_activeReadOperations.remove(&readOperation);
+
+        if (m_activeReadOperations.isEmpty())
+            m_readOperationTimeoutTimer.stop();
+        
         dispatchPendingReadOperations();
 
         LOG(NetworkCacheStorage, "(NetworkProcess) read complete success=%d", success);
     });
 }
 
+void Storage::cancelAllReadOperations()
+{
+    ASSERT(RunLoop::isMain());
+
+    for (auto& readOperation : m_activeReadOperations)
+        readOperation->cancel();
+
+    size_t pendingCount = 0;
+    for (int priority = maximumRetrievePriority; priority >= 0; --priority) {
+        auto& pendingRetrieveQueue = m_pendingReadOperationsByPriority[priority];
+        pendingCount += pendingRetrieveQueue.size();
+        for (auto it = pendingRetrieveQueue.rbegin(), end = pendingRetrieveQueue.rend(); it != end; ++it)
+            (*it)->cancel();
+        pendingRetrieveQueue.clear();
+    }
+
+    LOG(NetworkCacheStorage, "(NetworkProcess) retrieve timeout, canceled %u active and %zu pending", m_activeReadOperations.size(), pendingCount);
+}
+
 void Storage::dispatchPendingReadOperations()
 {
     ASSERT(RunLoop::isMain());
@@ -558,10 +611,7 @@
         auto& pendingRetrieveQueue = m_pendingReadOperationsByPriority[priority];
         if (pendingRetrieveQueue.isEmpty())
             continue;
-        auto readOperation = pendingRetrieveQueue.takeLast();
-        auto& read = *readOperation;
-        m_activeReadOperations.add(WTF::move(readOperation));
-        dispatchReadOperation(read);
+        dispatchReadOperation(pendingRetrieveQueue.takeLast());
     }
 }
 
@@ -591,11 +641,7 @@
             LOG(NetworkCacheStorage, "(NetworkProcess) limiting parallel writes");
             return;
         }
-        auto writeOperation = m_pendingWriteOperations.takeLast();
-        auto& write = *writeOperation;
-        m_activeWriteOperations.add(WTF::move(writeOperation));
-
-        dispatchWriteOperation(write);
+        dispatchWriteOperation(m_pendingWriteOperations.takeLast());
     }
 }
 
@@ -605,11 +651,13 @@
     return bodyData.size() > maximumInlineBodySize;
 }
 
-void Storage::dispatchWriteOperation(WriteOperation& writeOperation)
+void Storage::dispatchWriteOperation(std::unique_ptr<WriteOperation> writeOperationPtr)
 {
     ASSERT(RunLoop::isMain());
-    ASSERT(m_activeWriteOperations.contains(&writeOperation));
 
+    auto& writeOperation = *writeOperationPtr;
+    m_activeWriteOperations.add(WTF::move(writeOperationPtr));
+
     // This was added already when starting the store but filter might have been wiped.
     addToRecordFilter(writeOperation.record.key);
 

Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h (187957 => 187958)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h	2015-08-05 10:25:41 UTC (rev 187957)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h	2015-08-05 10:27:18 UTC (rev 187958)
@@ -107,12 +107,13 @@
     void shrink();
 
     struct ReadOperation;
-    void dispatchReadOperation(ReadOperation&);
+    void dispatchReadOperation(std::unique_ptr<ReadOperation>);
     void dispatchPendingReadOperations();
     void finishReadOperation(ReadOperation&);
+    void cancelAllReadOperations();
 
     struct WriteOperation;
-    void dispatchWriteOperation(WriteOperation&);
+    void dispatchWriteOperation(std::unique_ptr<WriteOperation>);
     void dispatchPendingWriteOperations();
     void finishWriteOperation(WriteOperation&);
 
@@ -150,6 +151,7 @@
     static const int maximumRetrievePriority = 4;
     Deque<std::unique_ptr<ReadOperation>> m_pendingReadOperationsByPriority[maximumRetrievePriority + 1];
     HashSet<std::unique_ptr<ReadOperation>> m_activeReadOperations;
+    WebCore::Timer m_readOperationTimeoutTimer;
 
     Deque<std::unique_ptr<WriteOperation>> m_pendingWriteOperations;
     HashSet<std::unique_ptr<WriteOperation>> m_activeWriteOperations;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to