WebKit Bugzilla
Attachment 342424 Details for
Bug 186520
: Add performance logging for slow cache retrieves
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
patch
cache-retrieve-timing-logging-2.patch (text/plain), 22.31 KB, created by
Antti Koivisto
on 2018-06-11 06:53:52 PDT
(
hide
)
Description:
patch
Filename:
MIME Type:
Creator:
Antti Koivisto
Created:
2018-06-11 06:53:52 PDT
Size:
22.31 KB
patch
obsolete
>Index: Source/WebKit/ChangeLog >=================================================================== >--- Source/WebKit/ChangeLog (revision 232709) >+++ Source/WebKit/ChangeLog (working copy) >@@ -1,3 +1,55 @@ >+2018-06-11 Antti Koivisto <antti@apple.com> >+ >+ Add performance logging for slow cache retrieves >+ https://bugs.webkit.org/show_bug.cgi?id=186520 >+ <rdar://problem/41002070> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ We sometimes see slow cache retrieves in logs. Add some more logging to better analyze these cases. >+ >+ This patch adds timings to all cache storage retrieve operations and passes them up to the client. >+ We then log the timings on NetworkResourceLoader levels if needed. Items logged include >+ >+ - total retrieve time >+ - dispatch delay and number of resources dispatched before this one >+ - record I/O time >+ - blob I/O time >+ - whether cache shrink was in progress >+ - whether cache synchronization was in progress >+ - cancellation >+ >+ * NetworkProcess/NetworkResourceLoader.cpp: >+ (WebKit::NetworkResourceLoader::retrieveCacheEntry): >+ (WebKit::NetworkResourceLoader::logSlowCacheRetrieveIfNeeded): >+ >+ Log if the retrieve took more than 1s. >+ >+ * NetworkProcess/NetworkResourceLoader.h: >+ * NetworkProcess/cache/CacheStorageEngineCaches.cpp: >+ (WebKit::CacheStorage::Caches::readRecord): >+ * NetworkProcess/cache/NetworkCache.cpp: >+ (WebKit::NetworkCache::Cache::retrieve): >+ (WebKit::NetworkCache::Cache::completeRetrieve): >+ (WebKit::NetworkCache::Cache::retrieveData): >+ * NetworkProcess/cache/NetworkCache.h: >+ * NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp: >+ (WebKit::NetworkCache::SpeculativeLoadManager::retrieveEntryFromStorage): >+ (WebKit::NetworkCache::SpeculativeLoadManager::retrieveSubresourcesEntry): >+ >+ SpeculativeLoadManager does not records specific timings yet but at least we do log when they occur. >+ >+ * NetworkProcess/cache/NetworkCacheStorage.cpp: >+ (WebKit::NetworkCache::Storage::ReadOperation::cancel): >+ (WebKit::NetworkCache::Storage::ReadOperation::finish): >+ >+ Record timing info in ReadOperations. >+ >+ (WebKit::NetworkCache::Storage::dispatchReadOperation): >+ (WebKit::NetworkCache::retrieveFromMemory): >+ (WebKit::NetworkCache::Storage::retrieve): >+ * NetworkProcess/cache/NetworkCacheStorage.h: >+ > 2018-06-10 Carlos Garcia Campos <cgarcia@igalia.com> > > [GTK][WPE] Add API run run javascript from a WebKitWebView in an isolated world >Index: Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp >=================================================================== >--- Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp (revision 232538) >+++ Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp (working copy) >@@ -215,7 +215,7 @@ void NetworkResourceLoader::retrieveCach > ASSERT(canUseCache(request)); > > RefPtr<NetworkResourceLoader> loader(this); >- m_cache->retrieve(request, { m_parameters.webPageID, m_parameters.webFrameID }, [this, loader = WTFMove(loader), request = ResourceRequest { request }](auto entry) mutable { >+ m_cache->retrieve(request, { m_parameters.webPageID, m_parameters.webFrameID }, [this, loader = WTFMove(loader), request = ResourceRequest { request }](auto entry, auto info) mutable { > #if RELEASE_LOG_DISABLED > UNUSED_PARAM(this); > #endif >@@ -223,6 +223,9 @@ void NetworkResourceLoader::retrieveCach > // The loader has been aborted and is only held alive by this lambda. > return; > } >+ >+ logSlowCacheRetrieveIfNeeded(info); >+ > if (!entry) { > 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()); > loader->startNetworkLoad(WTFMove(request), FirstLoad::Yes); >@@ -1081,4 +1084,34 @@ void NetworkResourceLoader::enqueueSecur > send(Messages::WebPage::EnqueueSecurityPolicyViolationEvent { m_parameters.webFrameID, WTFMove(eventInit) }, m_parameters.webPageID); > } > >+void NetworkResourceLoader::logSlowCacheRetrieveIfNeeded(const NetworkCache::Cache::RetrieveInfo& info) >+{ >+ if (!isAlwaysOnLoggingAllowed()) >+ return; >+ auto duration = info.completionTime - info.startTime; >+ if (duration < 1_s) >+ return; >+ RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Took %.0fms, priority %d", duration.milliseconds(), info.priority); >+ if (info.wasSpeculativeLoad) >+ RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Was speculative load"); >+ if (!info.storageTimings.startTime) >+ return; >+ RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Storage retrieve time %.0fms", (info.storageTimings.completionTime - info.storageTimings.startTime).milliseconds()); >+ if (info.storageTimings.dispatchTime) { >+ auto time = (info.storageTimings.dispatchTime - info.storageTimings.startTime).milliseconds(); >+ auto count = info.storageTimings.dispatchCountAtDispatch - info.storageTimings.dispatchCountAtStart; >+ RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Dispatch delay %.0fms, dispatched %lu resources first", time, count); >+ } >+ if (info.storageTimings.recordIOStartTime) >+ RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Record I/O time %.0fms", (info.storageTimings.recordIOEndTime - info.storageTimings.recordIOStartTime).milliseconds()); >+ if (info.storageTimings.blobIOStartTime) >+ RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Blob I/O time %.0fms", (info.storageTimings.blobIOEndTime - info.storageTimings.blobIOStartTime).milliseconds()); >+ if (info.storageTimings.synchronizationInProgressAtDispatch) >+ RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Synchronization was in progress"); >+ if (info.storageTimings.shrinkInProgressAtDispatch) >+ RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Shrink was in progress"); >+ if (info.storageTimings.wasCanceled) >+ RELEASE_LOG_IF_ALLOWED("logSlowCacheRetrieveIfNeeded: Retrieve was canceled"); >+} >+ > } // namespace WebKit >Index: Source/WebKit/NetworkProcess/NetworkResourceLoader.h >=================================================================== >--- Source/WebKit/NetworkProcess/NetworkResourceLoader.h (revision 232538) >+++ Source/WebKit/NetworkProcess/NetworkResourceLoader.h (working copy) >@@ -177,6 +177,8 @@ private: > void sendCSPViolationReport(WebCore::URL&&, Ref<WebCore::FormData>&&) final; > void enqueueSecurityPolicyViolationEvent(WebCore::SecurityPolicyViolationEvent::Init&&) final; > >+ void logSlowCacheRetrieveIfNeeded(const NetworkCache::Cache::RetrieveInfo&); >+ > const NetworkResourceLoadParameters m_parameters; > > Ref<NetworkConnectionToWebProcess> m_connection; >Index: Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp >=================================================================== >--- Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp (revision 232538) >+++ Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp (working copy) >@@ -508,7 +508,7 @@ void Caches::readRecord(const NetworkCac > return; > } > >- m_storage->retrieve(key, 4, [protectedStorage = makeRef(*m_storage), callback = WTFMove(callback)](std::unique_ptr<Storage::Record> storage) mutable { >+ m_storage->retrieve(key, 4, [protectedStorage = makeRef(*m_storage), callback = WTFMove(callback)](std::unique_ptr<Storage::Record> storage, const Storage::Timings&) mutable { > if (!storage) { > callback(makeUnexpected(Error::ReadDisk)); > return false; >Index: Source/WebKit/NetworkProcess/cache/NetworkCache.cpp >=================================================================== >--- Source/WebKit/NetworkProcess/cache/NetworkCache.cpp (revision 232538) >+++ Source/WebKit/NetworkProcess/cache/NetworkCache.cpp (working copy) >@@ -309,7 +309,7 @@ static StoreDecision makeStoreDecision(c > return StoreDecision::Yes; > } > >-void Cache::retrieve(const WebCore::ResourceRequest& request, const GlobalFrameID& frameID, Function<void (std::unique_ptr<Entry>)>&& completionHandler) >+void Cache::retrieve(const WebCore::ResourceRequest& request, const GlobalFrameID& frameID, RetrieveCompletionHandler&& completionHandler) > { > ASSERT(request.url().protocolIsInHTTPFamily()); > >@@ -319,6 +319,11 @@ void Cache::retrieve(const WebCore::Reso > m_statistics->recordRetrievalRequest(frameID.first); > > Key storageKey = makeCacheKey(request); >+ auto priority = static_cast<unsigned>(request.priority()); >+ >+ RetrieveInfo info; >+ info.startTime = WallTime::now(); >+ info.priority = priority; > > #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) > bool canUseSpeculativeRevalidation = m_speculativeLoadManager && !request.isConditional() && !cachePolicyAllowsExpired(request.cachePolicy()); >@@ -331,33 +336,33 @@ void Cache::retrieve(const WebCore::Reso > if (m_statistics) > m_statistics->recordNotUsingCacheForRequest(frameID.first, storageKey, request, retrieveDecision); > >- completionHandler(nullptr); >+ completeRetrieve(WTFMove(completionHandler), nullptr, info); > return; > } > > #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) > if (canUseSpeculativeRevalidation && m_speculativeLoadManager->canRetrieve(storageKey, request, frameID)) { >- m_speculativeLoadManager->retrieve(storageKey, [request, completionHandler = WTFMove(completionHandler)](std::unique_ptr<Entry> entry) { >+ m_speculativeLoadManager->retrieve(storageKey, [request, completionHandler = WTFMove(completionHandler), info = WTFMove(info)](std::unique_ptr<Entry> entry) mutable { >+ info.wasSpeculativeLoad = true; > if (entry && WebCore::verifyVaryingRequestHeaders(entry->varyingRequestHeaders(), request)) >- completionHandler(WTFMove(entry)); >+ completeRetrieve(WTFMove(completionHandler), WTFMove(entry), info); > else >- completionHandler(nullptr); >+ completeRetrieve(WTFMove(completionHandler), nullptr, info); > }); > return; > } > #endif > >- auto startTime = WallTime::now(); >- auto priority = static_cast<unsigned>(request.priority()); >+ m_storage->retrieve(storageKey, priority, [this, protectedThis = makeRef(*this), request, completionHandler = WTFMove(completionHandler), info = WTFMove(info), storageKey, frameID](auto record, auto timings) mutable { >+ info.storageTimings = timings; > >- m_storage->retrieve(storageKey, priority, [this, protectedThis = makeRef(*this), request, completionHandler = WTFMove(completionHandler), startTime, storageKey, frameID](auto record) { > if (!record) { > LOG(NetworkCache, "(NetworkProcess) not found in storage"); > > if (m_statistics) > m_statistics->recordRetrievalFailure(frameID.first, storageKey, request); > >- completionHandler(nullptr); >+ completeRetrieve(WTFMove(completionHandler), nullptr, info); > return false; > } > >@@ -377,12 +382,10 @@ void Cache::retrieve(const WebCore::Reso > }; > > #if !LOG_DISABLED >- auto elapsed = WallTime::now() - startTime; >+ auto elapsed = WallTime::now() - info.startTime; > 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>()); >-#else >- UNUSED_PARAM(startTime); > #endif >- completionHandler(WTFMove(entry)); >+ completeRetrieve(WTFMove(completionHandler), WTFMove(entry), info); > > if (m_statistics) > m_statistics->recordRetrievedCachedEntry(frameID.first, storageKey, request, useDecision); >@@ -390,6 +393,11 @@ void Cache::retrieve(const WebCore::Reso > }); > } > >+void Cache::completeRetrieve(RetrieveCompletionHandler&& handler, std::unique_ptr<Entry> entry, RetrieveInfo& info) >+{ >+ info.completionTime = WallTime::now(); >+ handler(WTFMove(entry), info); >+} > > std::unique_ptr<Entry> Cache::makeEntry(const WebCore::ResourceRequest& request, const WebCore::ResourceResponse& response, RefPtr<WebCore::SharedBuffer>&& responseData) > { >@@ -621,7 +629,7 @@ String Cache::recordsPath() const > void Cache::retrieveData(const DataKey& dataKey, Function<void (const uint8_t* data, size_t size)> completionHandler) > { > Key key { dataKey, m_storage->salt() }; >- m_storage->retrieve(key, 4, [completionHandler = WTFMove(completionHandler)] (auto record) { >+ m_storage->retrieve(key, 4, [completionHandler = WTFMove(completionHandler)] (auto record, auto) { > if (!record || !record->body.size()) { > completionHandler(nullptr, 0); > return true; >Index: Source/WebKit/NetworkProcess/cache/NetworkCache.h >=================================================================== >--- Source/WebKit/NetworkProcess/cache/NetworkCache.h (revision 232538) >+++ Source/WebKit/NetworkProcess/cache/NetworkCache.h (working copy) >@@ -102,7 +102,17 @@ public: > void setCapacity(size_t); > > // Completion handler may get called back synchronously on failure. >- void retrieve(const WebCore::ResourceRequest&, const GlobalFrameID&, Function<void (std::unique_ptr<Entry>)>&&); >+ struct RetrieveInfo { >+ WallTime startTime; >+ WallTime completionTime; >+ unsigned priority; >+ Storage::Timings storageTimings; >+ bool wasSpeculativeLoad { false }; >+ >+ WTF_MAKE_FAST_ALLOCATED; >+ }; >+ using RetrieveCompletionHandler = Function<void (std::unique_ptr<Entry>, const RetrieveInfo&)>; >+ void retrieve(const WebCore::ResourceRequest&, const GlobalFrameID&, RetrieveCompletionHandler&&); > std::unique_ptr<Entry> store(const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, RefPtr<WebCore::SharedBuffer>&&, Function<void (MappedBody&)>&&); > std::unique_ptr<Entry> storeRedirect(const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, const WebCore::ResourceRequest& redirectRequest); > std::unique_ptr<Entry> update(const WebCore::ResourceRequest&, const GlobalFrameID&, const Entry&, const WebCore::ResourceResponse& validatingResponse); >@@ -140,6 +150,8 @@ private: > > Key makeCacheKey(const WebCore::ResourceRequest&); > >+ static void completeRetrieve(RetrieveCompletionHandler&&, std::unique_ptr<Entry>, RetrieveInfo&); >+ > String dumpFilePath() const; > void deleteDumpFile(); > >Index: Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp >=================================================================== >--- Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp (revision 232538) >+++ Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp (working copy) >@@ -416,7 +416,7 @@ void SpeculativeLoadManager::addPreloade > > void SpeculativeLoadManager::retrieveEntryFromStorage(const SubresourceInfo& info, RetrieveCompletionHandler&& completionHandler) > { >- m_storage.retrieve(info.key(), static_cast<unsigned>(info.priority()), [completionHandler = WTFMove(completionHandler)](auto record) { >+ m_storage.retrieve(info.key(), static_cast<unsigned>(info.priority()), [completionHandler = WTFMove(completionHandler)](auto record, auto timings) { > if (!record) { > completionHandler(nullptr); > return false; >@@ -571,7 +571,7 @@ void SpeculativeLoadManager::retrieveSub > { > ASSERT(storageKey.type() == "Resource"); > auto subresourcesStorageKey = makeSubresourcesKey(storageKey, m_storage.salt()); >- m_storage.retrieve(subresourcesStorageKey, static_cast<unsigned>(ResourceLoadPriority::Medium), [completionHandler = WTFMove(completionHandler)](auto record) { >+ m_storage.retrieve(subresourcesStorageKey, static_cast<unsigned>(ResourceLoadPriority::Medium), [completionHandler = WTFMove(completionHandler)](auto record, auto timings) { > if (!record) { > completionHandler(nullptr); > return false; >Index: Source/WebKit/NetworkProcess/cache/NetworkCacheStorage.cpp >=================================================================== >--- Source/WebKit/NetworkProcess/cache/NetworkCacheStorage.cpp (revision 232538) >+++ Source/WebKit/NetworkProcess/cache/NetworkCacheStorage.cpp (working copy) >@@ -71,6 +71,7 @@ public: > BlobStorage::Blob resultBodyBlob; > std::atomic<unsigned> activeCount { 0 }; > bool isCanceled { false }; >+ Timings timings; > }; > > void Storage::ReadOperation::cancel() >@@ -79,8 +80,10 @@ void Storage::ReadOperation::cancel() > > if (isCanceled) > return; >+ timings.completionTime = WallTime::now(); >+ timings.wasCanceled = true; > isCanceled = true; >- completionHandler(nullptr); >+ completionHandler(nullptr, timings); > } > > bool Storage::ReadOperation::finish() >@@ -95,7 +98,8 @@ bool Storage::ReadOperation::finish() > else > resultRecord = nullptr; > } >- return completionHandler(WTFMove(resultRecord)); >+ timings.completionTime = WallTime::now(); >+ return completionHandler(WTFMove(resultRecord), timings); > } > > struct Storage::WriteOperation { >@@ -644,6 +648,13 @@ void Storage::dispatchReadOperation(std: > auto& readOperation = *readOperationPtr; > m_activeReadOperations.add(WTFMove(readOperationPtr)); > >+ readOperation.timings.dispatchTime = WallTime::now(); >+ readOperation.timings.synchronizationInProgressAtDispatch = m_synchronizationInProgress; >+ readOperation.timings.shrinkInProgressAtDispatch = m_shrinkInProgress; >+ readOperation.timings.dispatchCountAtDispatch = m_readOperationDispatchCount; >+ >+ ++m_readOperationDispatchCount; >+ > // Avoid randomness during testing. > if (m_mode != Mode::Testing) { > // I/O pressure may make disk operations slow. If they start taking very long time we rather go to network. >@@ -660,8 +671,11 @@ void Storage::dispatchReadOperation(std: > if (shouldGetBodyBlob) > ++readOperation.activeCount; > >+ readOperation.timings.recordIOStartTime = WallTime::now(); >+ > auto channel = IOChannel::open(recordPath, IOChannel::Type::Read); > channel->read(0, std::numeric_limits<size_t>::max(), &ioQueue(), [this, &readOperation](const Data& fileData, int error) { >+ readOperation.timings.recordIOEndTime = WallTime::now(); > if (!error) > readRecord(readOperation, fileData); > finishReadOperation(readOperation); >@@ -669,8 +683,12 @@ void Storage::dispatchReadOperation(std: > > if (shouldGetBodyBlob) { > // Read the blob in parallel with the record read. >+ readOperation.timings.blobIOStartTime = WallTime::now(); >+ > auto blobPath = blobPathForKey(readOperation.key); > readOperation.resultBodyBlob = m_blobStorage.get(blobPath); >+ >+ readOperation.timings.blobIOEndTime = WallTime::now(); > finishReadOperation(readOperation); > } > }); >@@ -747,7 +765,7 @@ template <class T> bool retrieveFromMemo > if (operation->record.key == key) { > LOG(NetworkCacheStorage, "(NetworkProcess) found write operation in progress"); > RunLoop::main().dispatch([record = operation->record, completionHandler = WTFMove(completionHandler)] { >- completionHandler(std::make_unique<Storage::Record>(record)); >+ completionHandler(std::make_unique<Storage::Record>(record), { }); > }); > return true; > } >@@ -839,12 +857,12 @@ void Storage::retrieve(const Key& key, u > ASSERT(!key.isNull()); > > if (!m_capacity) { >- completionHandler(nullptr); >+ completionHandler(nullptr, { }); > return; > } > > if (!mayContain(key)) { >- completionHandler(nullptr); >+ completionHandler(nullptr, { }); > return; > } > >@@ -854,6 +872,10 @@ void Storage::retrieve(const Key& key, u > return; > > auto readOperation = std::make_unique<ReadOperation>(*this, key, WTFMove(completionHandler)); >+ >+ readOperation->timings.startTime = WallTime::now(); >+ readOperation->timings.dispatchCountAtStart = m_readOperationDispatchCount; >+ > m_pendingReadOperationsByPriority[priority].prepend(WTFMove(readOperation)); > dispatchPendingReadOperations(); > } >Index: Source/WebKit/NetworkProcess/cache/NetworkCacheStorage.h >=================================================================== >--- Source/WebKit/NetworkProcess/cache/NetworkCacheStorage.h (revision 232538) >+++ Source/WebKit/NetworkProcess/cache/NetworkCacheStorage.h (working copy) >@@ -50,19 +50,37 @@ public: > static RefPtr<Storage> open(const String& cachePath, Mode); > > struct Record { >- WTF_MAKE_FAST_ALLOCATED; >- public: > Key key; > WallTime timeStamp; > Data header; > Data body; > std::optional<SHA1::Digest> bodyHash; >+ >+ WTF_MAKE_FAST_ALLOCATED; >+ }; >+ >+ struct Timings { >+ WallTime startTime; >+ WallTime dispatchTime; >+ WallTime recordIOStartTime; >+ WallTime recordIOEndTime; >+ WallTime blobIOStartTime; >+ WallTime blobIOEndTime; >+ WallTime completionTime; >+ size_t dispatchCountAtStart { 0 }; >+ size_t dispatchCountAtDispatch { 0 }; >+ bool synchronizationInProgressAtDispatch { false }; >+ bool shrinkInProgressAtDispatch { false }; >+ bool wasCanceled { false }; >+ >+ WTF_MAKE_FAST_ALLOCATED; > }; >+ > // This may call completion handler synchronously on failure. >- typedef Function<bool (std::unique_ptr<Record>)> RetrieveCompletionHandler; >+ using RetrieveCompletionHandler = Function<bool (std::unique_ptr<Record>, const Timings&)>; > void retrieve(const Key&, unsigned priority, RetrieveCompletionHandler&&); > >- typedef Function<void (const Data& mappedBody)> MappedBodyHandler; >+ using MappedBodyHandler = Function<void (const Data& mappedBody)>; > void store(const Record&, MappedBodyHandler&&, CompletionHandler<void()>&& = { }); > > void remove(const Key&); >@@ -163,6 +181,7 @@ private: > > bool m_synchronizationInProgress { false }; > bool m_shrinkInProgress { false }; >+ size_t m_readOperationDispatchCount { 0 }; > > Vector<Key::HashType> m_recordFilterHashesAddedDuringSynchronization; > Vector<Key::HashType> m_blobFilterHashesAddedDuringSynchronization;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 186520
:
342423
|
342424
|
342427
|
342428
|
342455