Bug 205015

Summary: Navigation from empty page doesn't use cached web process
Product: WebKit Reporter: Ben Nham <nham>
Component: Page LoadingAssignee: Ben Nham <nham>
Status: REOPENED ---    
Severity: Normal CC: beidson, cdumez, commit-queue, nham, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on: 205433    
Bug Blocks:    
Attachments:
Description Flags
Patch
none
test case for window.open (unused)
none
Patch
none
Patch none

Description Ben Nham 2019-12-09 09:55:54 PST
When navigating from an empty page to another domain foo.com, we always use the source WebProcess (which is basically uninitialized) rather than using an already-initialized cached WebProcess that has navigated to foo.com. The cached WebProcess should probably be preferred since it has more relevant cached resources available to it (e.g. memory cache, JS bytecode cache, prewarmed fonts, ...).
Comment 1 Ben Nham 2019-12-09 10:04:14 PST
<rdar://problem/57703742>
Comment 2 Ben Nham 2019-12-09 10:06:29 PST
Created attachment 385162 [details]
Patch
Comment 3 Ben Nham 2019-12-09 10:07:41 PST
Comment on attachment 385162 [details]
Patch

For perf testing purposes, this mainly affects the first warm page load on Mac PLT5. The perf bots show that this speeds up that first page load by 10-15% across all devices; the overall impact is 0.4%-1.5% depending on the device.
Comment 4 Chris Dumez 2019-12-10 10:46:54 PST
Comment on attachment 385162 [details]
Patch

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

The patch is not safe as is because it causes a process-swap in cases where we know it is not OK to process-swap (e.g. when navigation.openedByDOMWithOpener() returns true). If a page does a window.open() of another, we cannot process swap due to the opener link.

> Source/WebKit/UIProcess/WebProcessPool.cpp:2142
> +        if (!targetRegistrableDomain.isEmpty()) {

We should write an API test for this. See existing ProcessSwap API tests.
Comment 5 Alexey Proskuryakov 2019-12-13 23:03:24 PST
> The patch is not safe as is because it causes a process-swap in cases where
> we know it is not OK to process-swap (e.g. when
> navigation.openedByDOMWithOpener() returns true). If a page does a
> window.open() of another, we cannot process swap due to the opener link.

Is it possible to add a test for this too?
Comment 6 Ben Nham 2019-12-14 13:18:31 PST
Created attachment 385697 [details]
test case for window.open (unused)
Comment 7 Ben Nham 2019-12-14 13:19:17 PST
Created attachment 385698 [details]
Patch
Comment 8 Ben Nham 2019-12-14 13:25:43 PST
Comment on attachment 385698 [details]
Patch

I discussed this offline with Chris and he thinks it's more correct and less error-prone in the future if we move the hasCommittedAnyProvisionalLoads block to near the end of the function after all the special cases (e.g. opened by window.open) have been handled. I've done that in this patch.

Note that there are already multiple test cases that test various window.open scenarios, e.g. "if a page does a window.open() of another, we cannot process swap due to the opener link". Those tests passed with the previous patch and still pass with the current patch with the hasCommittedAnyProvisionalLoads block moved down.

I spent quite a bit of time trying to write a rather convoluted test case that would cause a WebProcess to spawn with an empty document, while also being opened with window.open, but that led to nothing since the sourceProcess always ends up being the process that executed the window.open. See the attached unused test case for an example.

However, I did write a test case for the behavior that I added, which is that we should prefer a cached process over the current process if the current process hasn't committed any provisional loads.
Comment 9 Chris Dumez 2019-12-14 15:20:12 PST
Comment on attachment 385698 [details]
Patch

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

Looks good.

> Source/WebKit/ChangeLog:15
> +        Add an API test.

"Added"

> Source/WebKit/UIProcess/WebProcessPool.cpp:2208
> +            LOG(ProcessSwapping, "(ProcessSwapping) Reusing a previously cached process with pid %i to continue navigation to URL %s in place of pid %i that hasn't committed any provisional loads", process->processIdentifier(), targetURL.string().utf8().data(), sourceProcess->processIdentifier());

I don't mind you adding a LOG() that contains the URL since this is debug only. However, there should definitely be a RELEASE_LOG() like in the rest of this function to facilitate debugging in release builds. You also cannot log the URL or domain in the RELEASE_LOG() though.
Comment 10 Ben Nham 2019-12-16 10:03:33 PST
Created attachment 385776 [details]
Patch
Comment 11 Ben Nham 2019-12-16 10:04:44 PST
Comment on attachment 385776 [details]
Patch

The target domain in the LOG doesn't seem that useful (unless there is a bug in WebProcessCache, which would be a much bigger problem somewhere else), so just remove that and make it a RELEASE_LOG.
Comment 12 WebKit Commit Bot 2019-12-17 13:42:29 PST
Comment on attachment 385776 [details]
Patch

Clearing flags on attachment: 385776

Committed r253646: <https://trac.webkit.org/changeset/253646>
Comment 13 WebKit Commit Bot 2019-12-17 13:42:30 PST
All reviewed patches have been landed.  Closing bug.
Comment 14 WebKit Commit Bot 2019-12-18 21:20:24 PST
Re-opened since this is blocked by bug 205433