Bug 226277 - Make CacheStorageEngine use the same WorkQueue as StorageQuotaManager
Summary: Make CacheStorageEngine use the same WorkQueue as StorageQuotaManager
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit Misc. (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Sihui Liu
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2021-05-26 10:04 PDT by Sihui Liu
Modified: 2021-06-02 10:05 PDT (History)
6 users (show)

See Also:


Attachments
Patch (15.52 KB, patch)
2021-05-26 10:20 PDT, Sihui Liu
no flags Details | Formatted Diff | Diff
Patch (16.62 KB, patch)
2021-05-27 11:19 PDT, Sihui Liu
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (16.52 KB, patch)
2021-05-27 12:00 PDT, Sihui Liu
no flags Details | Formatted Diff | Diff
Patch (19.40 KB, patch)
2021-05-28 10:10 PDT, Sihui Liu
sihui_liu: review?
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Sihui Liu 2021-05-26 10:04:49 PDT
...
Comment 1 Sihui Liu 2021-05-26 10:20:42 PDT
Created attachment 429771 [details]
Patch
Comment 2 Chris Dumez 2021-05-26 10:27:40 PDT
Comment on attachment 429771 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=429771&action=review

> Source/WebKit/ChangeLog:8
> +        Make one WorkQueue per SessionStorageQuotaManager and use it for both StorageQuotaManagar and CacheStorageEngine.

typo: StorageQuotaManagar

> Source/WebKit/NetworkProcess/NetworkProcess.cpp:2519
> +RefPtr<WorkQueue> NetworkProcess::storageSessionQueue(PAL::SessionID sessionID)

Do different storage sessions really need different work queues or could they all share the same static WorkQueue. Not that we'd be less likely to have threading bugs if they shared the same queue.

> Source/WebKit/NetworkProcess/NetworkProcess.h:349
> +    RefPtr<WorkQueue> storageSessionQueue(PAL::SessionID);

Seems like this should be const.
Comment 3 Sihui Liu 2021-05-26 11:02:36 PDT
(In reply to Chris Dumez from comment #2)
> Comment on attachment 429771 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=429771&action=review
> 
> > Source/WebKit/ChangeLog:8
> > +        Make one WorkQueue per SessionStorageQuotaManager and use it for both StorageQuotaManagar and CacheStorageEngine.
> 
> typo: StorageQuotaManagar
> 
> > Source/WebKit/NetworkProcess/NetworkProcess.cpp:2519
> > +RefPtr<WorkQueue> NetworkProcess::storageSessionQueue(PAL::SessionID sessionID)
> 
> Do different storage sessions really need different work queues or could
> they all share the same static WorkQueue. Not that we'd be less likely to
> have threading bugs if they shared the same queue.
> 

'Not that' or 'Note that'? It means opposite things :)!

My thought is if they share the same queue, requests from persistent session will slow down the ones from ephemeral session, which do not need disk access. Requests from persistent session are probably fine as the bottleneck is probably disk I/O even if they don't share and sharing means less locking.

> > Source/WebKit/NetworkProcess/NetworkProcess.h:349
> > +    RefPtr<WorkQueue> storageSessionQueue(PAL::SessionID);
> 
> Seems like this should be const.
Comment 4 Chris Dumez 2021-05-26 11:04:44 PDT
(In reply to Sihui Liu from comment #3)
> (In reply to Chris Dumez from comment #2)
> > Comment on attachment 429771 [details]
> > Patch
> > 
> > View in context:
> > https://bugs.webkit.org/attachment.cgi?id=429771&action=review
> > 
> > > Source/WebKit/ChangeLog:8
> > > +        Make one WorkQueue per SessionStorageQuotaManager and use it for both StorageQuotaManagar and CacheStorageEngine.
> > 
> > typo: StorageQuotaManagar
> > 
> > > Source/WebKit/NetworkProcess/NetworkProcess.cpp:2519
> > > +RefPtr<WorkQueue> NetworkProcess::storageSessionQueue(PAL::SessionID sessionID)
> > 
> > Do different storage sessions really need different work queues or could
> > they all share the same static WorkQueue. Not that we'd be less likely to
> > have threading bugs if they shared the same queue.
> > 
> 
> 'Not that' or 'Note that'? It means opposite things :)!
> 
> My thought is if they share the same queue, requests from persistent session
> will slow down the ones from ephemeral session, which do not need disk
> access. Requests from persistent session are probably fine as the bottleneck
> is probably disk I/O even if they don't share and sharing means less locking.

That assumes we have parallel work for both persistent and non-persistent sessions. I personally don't think that's super common.
Comment 5 Chris Dumez 2021-05-26 12:45:38 PDT
(In reply to Chris Dumez from comment #4)
> (In reply to Sihui Liu from comment #3)
> > (In reply to Chris Dumez from comment #2)
> > > Comment on attachment 429771 [details]
> > > Patch
> > > 
> > > View in context:
> > > https://bugs.webkit.org/attachment.cgi?id=429771&action=review
> > > 
> > > > Source/WebKit/ChangeLog:8
> > > > +        Make one WorkQueue per SessionStorageQuotaManager and use it for both StorageQuotaManagar and CacheStorageEngine.
> > > 
> > > typo: StorageQuotaManagar
> > > 
> > > > Source/WebKit/NetworkProcess/NetworkProcess.cpp:2519
> > > > +RefPtr<WorkQueue> NetworkProcess::storageSessionQueue(PAL::SessionID sessionID)
> > > 
> > > Do different storage sessions really need different work queues or could
> > > they all share the same static WorkQueue. Not that we'd be less likely to
> > > have threading bugs if they shared the same queue.
> > > 
> > 
> > 'Not that' or 'Note that'? It means opposite things :)!

Darn, I make this typo all the time :(

> > 
> > My thought is if they share the same queue, requests from persistent session
> > will slow down the ones from ephemeral session, which do not need disk
> > access. Requests from persistent session are probably fine as the bottleneck
> > is probably disk I/O even if they don't share and sharing means less locking.
> 
> That assumes we have parallel work for both persistent and non-persistent
> sessions. I personally don't think that's super common.
Comment 6 youenn fablet 2021-05-27 00:25:51 PDT
Comment on attachment 429771 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=429771&action=review

> Source/WebCore/storage/StorageQuotaManager.cpp:52
>      ASSERT(!isMainThread());

It seems ok to remove requestSpaceOnMainThread.
If the plan for IDB to call requestSpaceOnBackgroundThread in the shared work queue, that will lead to good simplifications.
But, IIRC, that was the hard part due to the IDB was implemented. Have you tried doing so?

> Source/WebKit/NetworkProcess/NetworkProcess.h:513
> +                return WebCore::StorageQuotaManager::create(quota, WTFMove(usageGetter), WTFMove(quotaIncreaseRequester), WTFMove(queue));

Quota management is independent per origin.
If one page of origin A triggers a prompt, it should not block page of origin B to also trigger the prompt.
Conceptually, it seems StorageQuotaManager should have its own queue and not share it with other managers.

> Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp:275
> +    m_ioQueue = m_networkProcess->storageSessionQueue(m_sessionID);

This queue is mostly used to read/write cache infrastructure files, like list of cache names, salt, origin...
The actual storage of cache entries is implemented through NetworkCache::Storage which is using concurrent queues for performance reasons.
I am not sure we are solving what we think we are solving with this patch. Computation of actual disk size will always be racy if there are ongoing operations.
Ultimately, if the web page wants to optimise prompting, it would be up to the web page to make careful sequential operations instead of doing several operations in parallel that may or may not hit the quota.

That said, removing requestSpaceOnMainThread is fine by me.
Comment 7 Sihui Liu 2021-05-27 09:33:21 PDT
(In reply to youenn fablet from comment #6)
> Comment on attachment 429771 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=429771&action=review
> 
> > Source/WebCore/storage/StorageQuotaManager.cpp:52
> >      ASSERT(!isMainThread());
> 
> It seems ok to remove requestSpaceOnMainThread.
> If the plan for IDB to call requestSpaceOnBackgroundThread in the shared
> work queue, that will lead to good simplifications.
> But, IIRC, that was the hard part due to the IDB was implemented. Have you
> tried doing so?

Yes, I tried to make IDB use WorkQueue (first step is creating a dedicated thread for JS serialization https://bugs.webkit.org/show_bug.cgi?id=226228).

>
> > Source/WebKit/NetworkProcess/NetworkProcess.h:513
> > +                return WebCore::StorageQuotaManager::create(quota, WTFMove(usageGetter), WTFMove(quotaIncreaseRequester), WTFMove(queue));
> 
> Quota management is independent per origin.
> If one page of origin A triggers a prompt, it should not block page of
> origin B to also trigger the prompt.
> Conceptually, it seems StorageQuotaManager should have its own queue and not
> share it with other managers.

Is it possible to show multiple quota prompts at the same time? If user can only see/handle one prompt at one time, it might be Okay. 

I use one queue per session as it simplifies things, e.g. fetching/deleting data for origins will be one task on the shared queue instead of multiple tasks on different queues, or when we stop storage activities (e.g. for suspension), we may just need to suspend the shared queue.

> 
> > Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp:275
> > +    m_ioQueue = m_networkProcess->storageSessionQueue(m_sessionID);
> 
> This queue is mostly used to read/write cache infrastructure files, like
> list of cache names, salt, origin...
> The actual storage of cache entries is implemented through
> NetworkCache::Storage which is using concurrent queues for performance
> reasons.
> I am not sure we are solving what we think we are solving with this patch.
> Computation of actual disk size will always be racy if there are ongoing
> operations.
> Ultimately, if the web page wants to optimise prompting, it would be up to
> the web page to make careful sequential operations instead of doing several
> operations in parallel that may or may not hit the quota.
> 
> That said, removing requestSpaceOnMainThread is fine by me.

Yes I think to make the disk usage accurate we should do all the writes at the same queue, or at least we should ensure granted writes happen before next quota check, which likely requires architectural change in Cache storage.

If necessary, we can also update the size file (based on estimate) at the shared queue, and correct size file periodically based on results from other queues of NetworkCache::Storage.
Comment 8 Sihui Liu 2021-05-27 11:19:05 PDT
Created attachment 429904 [details]
Patch
Comment 9 Sihui Liu 2021-05-27 12:00:11 PDT
Created attachment 429909 [details]
Patch
Comment 10 Chris Dumez 2021-05-27 15:32:20 PDT
API test failure looks related.
Comment 11 Sihui Liu 2021-05-28 10:10:26 PDT
Created attachment 430022 [details]
Patch
Comment 12 youenn fablet 2021-05-31 00:04:57 PDT
Comment on attachment 430022 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=430022&action=review

> Source/WebCore/storage/StorageQuotaManager.cpp:45
> +    , m_workQueue(queue)

WTFMove

> Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp:251
> +    if (!m_ioQueue || !m_networkProcess) {

It does not seem like m_ioQueue can be null now.

> Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp:262
> +    m_ioQueue->dispatch([storageQuotaManager, spaceRequested, callback = WTFMove(callback)]() mutable {

storageQuotaManager  = WTFMove(storageQuotaManager)

We should probably add a comment here to state why we have to hop in to ioQueue to request space.

> Tools/ChangeLog:8
> +        Update the test expectation as with this change cache request from one origin may block that from another.

I don't think we want to have that behavior.
If we go with that change, we should be able to have requests from different origins run in parallel.
As discussed offline, either with a queue per quota manager, or as you proposed, quota manager handling several callbacks in parallel.

> Tools/TestWebKitAPI/Tests/WebKitCocoa/StorageQuota.mm:83
> +    NSLog(@"sihuil: decideDatabaseQuotaForSecurityOrigin sets receivedQuotaDelegateCalled true");

to be removed here and below.
Comment 13 Radar WebKit Bug Importer 2021-06-02 10:05:20 PDT
<rdar://problem/78769703>