Changeset 232759 in webkit
- Timestamp:
- Jun 12, 2018 10:53:02 AM (6 years ago)
- Location:
- trunk/Source/WebKit
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r232744 r232759 1 2018-06-12 Antti Koivisto <antti@apple.com> 2 3 Add performance logging for slow cache retrieves 4 https://bugs.webkit.org/show_bug.cgi?id=186520 5 <rdar://problem/41002070> 6 7 Reviewed by Chris Dumez. 8 9 We sometimes see slow cache retrieves in logs. Add some more logging to better analyze these cases. 10 11 This patch adds timings to all cache storage retrieve operations and passes them up to the client. 12 We then log the timings on NetworkResourceLoader levels if needed. Items logged include 13 14 - total retrieve time 15 - dispatch delay and number of resources dispatched before this one 16 - record I/O time 17 - blob I/O time 18 - whether cache shrink was in progress 19 - whether cache synchronization was in progress 20 - cancellation 21 22 * NetworkProcess/NetworkResourceLoader.cpp: 23 (WebKit::NetworkResourceLoader::retrieveCacheEntry): 24 (WebKit::NetworkResourceLoader::logSlowCacheRetrieveIfNeeded): 25 26 Log if the retrieve took more than 1s. 27 28 * NetworkProcess/NetworkResourceLoader.h: 29 * NetworkProcess/cache/CacheStorageEngineCaches.cpp: 30 (WebKit::CacheStorage::Caches::readRecord): 31 * NetworkProcess/cache/NetworkCache.cpp: 32 (WebKit::NetworkCache::Cache::retrieve): 33 (WebKit::NetworkCache::Cache::completeRetrieve): 34 (WebKit::NetworkCache::Cache::retrieveData): 35 * NetworkProcess/cache/NetworkCache.h: 36 * NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp: 37 (WebKit::NetworkCache::SpeculativeLoadManager::retrieveEntryFromStorage): 38 (WebKit::NetworkCache::SpeculativeLoadManager::retrieveSubresourcesEntry): 39 40 SpeculativeLoadManager does not records specific timings yet but at least we do log when they occur. 41 42 * NetworkProcess/cache/NetworkCacheStorage.cpp: 43 (WebKit::NetworkCache::Storage::ReadOperation::cancel): 44 (WebKit::NetworkCache::Storage::ReadOperation::finish): 45 46 Record timing info in ReadOperations. 47 48 (WebKit::NetworkCache::Storage::dispatchReadOperation): 49 (WebKit::NetworkCache::retrieveFromMemory): 50 (WebKit::NetworkCache::Storage::retrieve): 51 * NetworkProcess/cache/NetworkCacheStorage.h: 52 1 53 2018-06-11 Carlos Garcia Campos <cgarcia@igalia.com> 2 54 -
trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp
r232217 r232759 216 216 217 217 RefPtr<NetworkResourceLoader> loader(this); 218 m_cache->retrieve(request, { m_parameters.webPageID, m_parameters.webFrameID }, [this, loader = WTFMove(loader), request = ResourceRequest { request }](auto entry) mutable { 219 #if RELEASE_LOG_DISABLED 220 UNUSED_PARAM(this); 221 #endif 218 m_cache->retrieve(request, { m_parameters.webPageID, m_parameters.webFrameID }, [this, loader = WTFMove(loader), request = ResourceRequest { request }](auto entry, auto info) mutable { 222 219 if (loader->hasOneRef()) { 223 220 // The loader has been aborted and is only held alive by this lambda. 224 221 return; 225 222 } 223 224 loader->logSlowCacheRetrieveIfNeeded(info); 225 226 226 if (!entry) { 227 227 RELEASE_LOG_IF_ALLOWED("retrieveCacheEntry: Resource not in cache (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous()); … … 1082 1082 } 1083 1083 1084 void NetworkResourceLoader::logSlowCacheRetrieveIfNeeded(const NetworkCache::Cache::RetrieveInfo& info) 1085 { 1086 #if RELEASE_LOG_DISABLED 1087 UNUSED_PARAM(info); 1088 #else 1089 if (!isAlwaysOnLoggingAllowed()) 1090 return; 1091 auto duration = info.completionTime - info.startTime; 1092 if (duration < 1_s) 1093 return; 1094 RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Took %.0fms, priority %d", duration.milliseconds(), info.priority); 1095 if (info.wasSpeculativeLoad) 1096 RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Was speculative load"); 1097 if (!info.storageTimings.startTime) 1098 return; 1099 RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Storage retrieve time %.0fms", (info.storageTimings.completionTime - info.storageTimings.startTime).milliseconds()); 1100 if (info.storageTimings.dispatchTime) { 1101 auto time = (info.storageTimings.dispatchTime - info.storageTimings.startTime).milliseconds(); 1102 auto count = info.storageTimings.dispatchCountAtDispatch - info.storageTimings.dispatchCountAtStart; 1103 RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Dispatch delay %.0fms, dispatched %lu resources first", time, count); 1104 } 1105 if (info.storageTimings.recordIOStartTime) 1106 RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Record I/O time %.0fms", (info.storageTimings.recordIOEndTime - info.storageTimings.recordIOStartTime).milliseconds()); 1107 if (info.storageTimings.blobIOStartTime) 1108 RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Blob I/O time %.0fms", (info.storageTimings.blobIOEndTime - info.storageTimings.blobIOStartTime).milliseconds()); 1109 if (info.storageTimings.synchronizationInProgressAtDispatch) 1110 RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Synchronization was in progress"); 1111 if (info.storageTimings.shrinkInProgressAtDispatch) 1112 RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Shrink was in progress"); 1113 if (info.storageTimings.wasCanceled) 1114 RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Retrieve was canceled"); 1115 #endif 1116 } 1117 1084 1118 } // namespace WebKit -
trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h
r232121 r232759 178 178 void enqueueSecurityPolicyViolationEvent(WebCore::SecurityPolicyViolationEvent::Init&&) final; 179 179 180 void logSlowCacheRetrieveIfNeeded(const NetworkCache::Cache::RetrieveInfo&); 181 180 182 const NetworkResourceLoadParameters m_parameters; 181 183 -
trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp
r229914 r232759 509 509 } 510 510 511 m_storage->retrieve(key, 4, [protectedStorage = makeRef(*m_storage), callback = WTFMove(callback)](std::unique_ptr<Storage::Record> storage ) mutable {511 m_storage->retrieve(key, 4, [protectedStorage = makeRef(*m_storage), callback = WTFMove(callback)](std::unique_ptr<Storage::Record> storage, const Storage::Timings&) mutable { 512 512 if (!storage) { 513 513 callback(makeUnexpected(Error::ReadDisk)); -
trunk/Source/WebKit/NetworkProcess/cache/NetworkCache.cpp
r232447 r232759 310 310 } 311 311 312 void Cache::retrieve(const WebCore::ResourceRequest& request, const GlobalFrameID& frameID, Function<void (std::unique_ptr<Entry>)>&& completionHandler)312 void Cache::retrieve(const WebCore::ResourceRequest& request, const GlobalFrameID& frameID, RetrieveCompletionHandler&& completionHandler) 313 313 { 314 314 ASSERT(request.url().protocolIsInHTTPFamily()); … … 320 320 321 321 Key storageKey = makeCacheKey(request); 322 auto priority = static_cast<unsigned>(request.priority()); 323 324 RetrieveInfo info; 325 info.startTime = MonotonicTime::now(); 326 info.priority = priority; 322 327 323 328 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) … … 332 337 m_statistics->recordNotUsingCacheForRequest(frameID.first, storageKey, request, retrieveDecision); 333 338 334 complet ionHandler(nullptr);339 completeRetrieve(WTFMove(completionHandler), nullptr, info); 335 340 return; 336 341 } … … 338 343 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) 339 344 if (canUseSpeculativeRevalidation && m_speculativeLoadManager->canRetrieve(storageKey, request, frameID)) { 340 m_speculativeLoadManager->retrieve(storageKey, [request, completionHandler = WTFMove(completionHandler)](std::unique_ptr<Entry> entry) { 345 m_speculativeLoadManager->retrieve(storageKey, [request, completionHandler = WTFMove(completionHandler), info = WTFMove(info)](std::unique_ptr<Entry> entry) mutable { 346 info.wasSpeculativeLoad = true; 341 347 if (entry && WebCore::verifyVaryingRequestHeaders(entry->varyingRequestHeaders(), request)) 342 complet ionHandler(WTFMove(entry));348 completeRetrieve(WTFMove(completionHandler), WTFMove(entry), info); 343 349 else 344 complet ionHandler(nullptr);350 completeRetrieve(WTFMove(completionHandler), nullptr, info); 345 351 }); 346 352 return; … … 348 354 #endif 349 355 350 auto startTime = WallTime::now(); 351 auto priority = static_cast<unsigned>(request.priority()); 352 353 m_storage->retrieve(storageKey, priority, [this, protectedThis = makeRef(*this), request, completionHandler = WTFMove(completionHandler), startTime, storageKey, frameID](auto record) { 356 m_storage->retrieve(storageKey, priority, [this, protectedThis = makeRef(*this), request, completionHandler = WTFMove(completionHandler), info = WTFMove(info), storageKey, frameID](auto record, auto timings) mutable { 357 info.storageTimings = timings; 358 354 359 if (!record) { 355 360 LOG(NetworkCache, "(NetworkProcess) not found in storage"); … … 358 363 m_statistics->recordRetrievalFailure(frameID.first, storageKey, request); 359 364 360 complet ionHandler(nullptr);365 completeRetrieve(WTFMove(completionHandler), nullptr, info); 361 366 return false; 362 367 } … … 378 383 379 384 #if !LOG_DISABLED 380 auto elapsed = WallTime::now() -startTime;385 auto elapsed = MonotonicTime::now() - info.startTime; 381 386 LOG(NetworkCache, "(NetworkProcess) retrieve complete useDecision=%d priority=%d time=%" PRIi64 "ms", static_cast<int>(useDecision), static_cast<int>(request.priority()), elapsed.millisecondsAs<int64_t>()); 382 #else 383 UNUSED_PARAM(startTime); 384 #endif 385 completionHandler(WTFMove(entry)); 387 #endif 388 completeRetrieve(WTFMove(completionHandler), WTFMove(entry), info); 386 389 387 390 if (m_statistics) … … 391 394 } 392 395 396 void Cache::completeRetrieve(RetrieveCompletionHandler&& handler, std::unique_ptr<Entry> entry, RetrieveInfo& info) 397 { 398 info.completionTime = MonotonicTime::now(); 399 handler(WTFMove(entry), info); 400 } 393 401 394 402 std::unique_ptr<Entry> Cache::makeEntry(const WebCore::ResourceRequest& request, const WebCore::ResourceResponse& response, RefPtr<WebCore::SharedBuffer>&& responseData) … … 622 630 { 623 631 Key key { dataKey, m_storage->salt() }; 624 m_storage->retrieve(key, 4, [completionHandler = WTFMove(completionHandler)] (auto record ) {632 m_storage->retrieve(key, 4, [completionHandler = WTFMove(completionHandler)] (auto record, auto) { 625 633 if (!record || !record->body.size()) { 626 634 completionHandler(nullptr, 0); -
trunk/Source/WebKit/NetworkProcess/cache/NetworkCache.h
r231484 r232759 103 103 104 104 // Completion handler may get called back synchronously on failure. 105 void retrieve(const WebCore::ResourceRequest&, const GlobalFrameID&, Function<void (std::unique_ptr<Entry>)>&&); 105 struct RetrieveInfo { 106 MonotonicTime startTime; 107 MonotonicTime completionTime; 108 unsigned priority; 109 Storage::Timings storageTimings; 110 bool wasSpeculativeLoad { false }; 111 112 WTF_MAKE_FAST_ALLOCATED; 113 }; 114 using RetrieveCompletionHandler = Function<void (std::unique_ptr<Entry>, const RetrieveInfo&)>; 115 void retrieve(const WebCore::ResourceRequest&, const GlobalFrameID&, RetrieveCompletionHandler&&); 106 116 std::unique_ptr<Entry> store(const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, RefPtr<WebCore::SharedBuffer>&&, Function<void (MappedBody&)>&&); 107 117 std::unique_ptr<Entry> storeRedirect(const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, const WebCore::ResourceRequest& redirectRequest); … … 141 151 Key makeCacheKey(const WebCore::ResourceRequest&); 142 152 153 static void completeRetrieve(RetrieveCompletionHandler&&, std::unique_ptr<Entry>, RetrieveInfo&); 154 143 155 String dumpFilePath() const; 144 156 void deleteDumpFile(); -
trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp
r230944 r232759 417 417 void SpeculativeLoadManager::retrieveEntryFromStorage(const SubresourceInfo& info, RetrieveCompletionHandler&& completionHandler) 418 418 { 419 m_storage.retrieve(info.key(), static_cast<unsigned>(info.priority()), [completionHandler = WTFMove(completionHandler)](auto record ) {419 m_storage.retrieve(info.key(), static_cast<unsigned>(info.priority()), [completionHandler = WTFMove(completionHandler)](auto record, auto timings) { 420 420 if (!record) { 421 421 completionHandler(nullptr); … … 572 572 ASSERT(storageKey.type() == "Resource"); 573 573 auto subresourcesStorageKey = makeSubresourcesKey(storageKey, m_storage.salt()); 574 m_storage.retrieve(subresourcesStorageKey, static_cast<unsigned>(ResourceLoadPriority::Medium), [completionHandler = WTFMove(completionHandler)](auto record ) {574 m_storage.retrieve(subresourcesStorageKey, static_cast<unsigned>(ResourceLoadPriority::Medium), [completionHandler = WTFMove(completionHandler)](auto record, auto timings) { 575 575 if (!record) { 576 576 completionHandler(nullptr); -
trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheStorage.cpp
r231708 r232759 72 72 std::atomic<unsigned> activeCount { 0 }; 73 73 bool isCanceled { false }; 74 Timings timings; 74 75 }; 75 76 … … 80 81 if (isCanceled) 81 82 return; 83 timings.completionTime = MonotonicTime::now(); 84 timings.wasCanceled = true; 82 85 isCanceled = true; 83 completionHandler(nullptr );86 completionHandler(nullptr, timings); 84 87 } 85 88 … … 96 99 resultRecord = nullptr; 97 100 } 98 return completionHandler(WTFMove(resultRecord)); 101 timings.completionTime = MonotonicTime::now(); 102 return completionHandler(WTFMove(resultRecord), timings); 99 103 } 100 104 … … 645 649 m_activeReadOperations.add(WTFMove(readOperationPtr)); 646 650 651 readOperation.timings.dispatchTime = MonotonicTime::now(); 652 readOperation.timings.synchronizationInProgressAtDispatch = m_synchronizationInProgress; 653 readOperation.timings.shrinkInProgressAtDispatch = m_shrinkInProgress; 654 readOperation.timings.dispatchCountAtDispatch = m_readOperationDispatchCount; 655 656 ++m_readOperationDispatchCount; 657 647 658 // Avoid randomness during testing. 648 659 if (m_mode != Mode::Testing) { … … 661 672 ++readOperation.activeCount; 662 673 674 readOperation.timings.recordIOStartTime = MonotonicTime::now(); 675 663 676 auto channel = IOChannel::open(recordPath, IOChannel::Type::Read); 664 677 channel->read(0, std::numeric_limits<size_t>::max(), &ioQueue(), [this, &readOperation](const Data& fileData, int error) { 678 readOperation.timings.recordIOEndTime = MonotonicTime::now(); 665 679 if (!error) 666 680 readRecord(readOperation, fileData); … … 670 684 if (shouldGetBodyBlob) { 671 685 // Read the blob in parallel with the record read. 686 readOperation.timings.blobIOStartTime = MonotonicTime::now(); 687 672 688 auto blobPath = blobPathForKey(readOperation.key); 673 689 readOperation.resultBodyBlob = m_blobStorage.get(blobPath); 690 691 readOperation.timings.blobIOEndTime = MonotonicTime::now(); 692 674 693 finishReadOperation(readOperation); 675 694 } … … 748 767 LOG(NetworkCacheStorage, "(NetworkProcess) found write operation in progress"); 749 768 RunLoop::main().dispatch([record = operation->record, completionHandler = WTFMove(completionHandler)] { 750 completionHandler(std::make_unique<Storage::Record>(record) );769 completionHandler(std::make_unique<Storage::Record>(record), { }); 751 770 }); 752 771 return true; … … 840 859 841 860 if (!m_capacity) { 842 completionHandler(nullptr );861 completionHandler(nullptr, { }); 843 862 return; 844 863 } 845 864 846 865 if (!mayContain(key)) { 847 completionHandler(nullptr );866 completionHandler(nullptr, { }); 848 867 return; 849 868 } … … 855 874 856 875 auto readOperation = std::make_unique<ReadOperation>(*this, key, WTFMove(completionHandler)); 876 877 readOperation->timings.startTime = MonotonicTime::now(); 878 readOperation->timings.dispatchCountAtStart = m_readOperationDispatchCount; 879 857 880 m_pendingReadOperationsByPriority[priority].prepend(WTFMove(readOperation)); 858 881 dispatchPendingReadOperations(); -
trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheStorage.h
r231484 r232759 35 35 #include <wtf/Function.h> 36 36 #include <wtf/HashSet.h> 37 #include <wtf/MonotonicTime.h> 37 38 #include <wtf/Optional.h> 38 39 #include <wtf/WallTime.h> … … 51 52 52 53 struct Record { 53 WTF_MAKE_FAST_ALLOCATED;54 public:55 54 Key key; 56 55 WallTime timeStamp; … … 58 57 Data body; 59 58 std::optional<SHA1::Digest> bodyHash; 60 }; 59 60 WTF_MAKE_FAST_ALLOCATED; 61 }; 62 63 struct Timings { 64 MonotonicTime startTime; 65 MonotonicTime dispatchTime; 66 MonotonicTime recordIOStartTime; 67 MonotonicTime recordIOEndTime; 68 MonotonicTime blobIOStartTime; 69 MonotonicTime blobIOEndTime; 70 MonotonicTime completionTime; 71 size_t dispatchCountAtStart { 0 }; 72 size_t dispatchCountAtDispatch { 0 }; 73 bool synchronizationInProgressAtDispatch { false }; 74 bool shrinkInProgressAtDispatch { false }; 75 bool wasCanceled { false }; 76 77 WTF_MAKE_FAST_ALLOCATED; 78 }; 79 61 80 // This may call completion handler synchronously on failure. 62 typedef Function<bool (std::unique_ptr<Record>)> RetrieveCompletionHandler;81 using RetrieveCompletionHandler = Function<bool (std::unique_ptr<Record>, const Timings&)>; 63 82 void retrieve(const Key&, unsigned priority, RetrieveCompletionHandler&&); 64 83 65 typedef Function<void (const Data& mappedBody)> MappedBodyHandler;84 using MappedBodyHandler = Function<void (const Data& mappedBody)>; 66 85 void store(const Record&, MappedBodyHandler&&, CompletionHandler<void()>&& = { }); 67 86 … … 164 183 bool m_synchronizationInProgress { false }; 165 184 bool m_shrinkInProgress { false }; 185 size_t m_readOperationDispatchCount { 0 }; 166 186 167 187 Vector<Key::HashType> m_recordFilterHashesAddedDuringSynchronization;
Note: See TracChangeset
for help on using the changeset viewer.