NEW 203165
First page load after WKWebView init waits for Networking process creation
https://bugs.webkit.org/show_bug.cgi?id=203165
Summary First page load after WKWebView init waits for Networking process creation
Ben Nham
Reported 2019-10-18 14:30:15 PDT
The very first page loaded by PLT5 is usually delayed by ~100-150 ms (i.e. time from when we ask the browser to load the URL to the time the first bytes are put on the wire). The reason for this is that WebProcess makes a sync call back to UIProcess, which is in the middle of doing other work, like making more views and then committing a CATransaction. I think this could be more than a test artifact, e.g. opening a URL in a new window seems like it would trigger a similar flow. PLT5 starts by creating a new browser window, which creates a WKWebView. Among other things, this causes us to take a WebProcess out of the pool and call SetWebsiteDataStore on it, which passes along some parameters like the session ID: ``` bool WebKit::AuxiliaryProcessProxy::send<Messages::WebProcess::SetWebsiteDataStoreParameters> WebKit::WebProcessProxy::setWebsiteDataStore WebKit::WebProcessPool::tryTakePrewarmedProcess WebKit::WebProcessPool::processForRegistrableDomain WebKit::WebPageProxy::launchProcess WebKit::WebPageProxy::launchInitialProcessIfNecessary ... +[BrowserWindowController openEmptyBrowserWindowController] Safari::PageLoadTestWithChrome::createNewWindow Safari::PageLoadTest::run ``` The WebProcess responds to this by turning right back around and issuing a sync IPC back to the UIProcess asking for a connection to the NetworkProcess: ``` bool IPC::Connection::sendSync<Messages::WebProcessProxy::GetNetworkProcessConnection> WebKit::getNetworkProcessConnection WebKit::WebProcess::ensureNetworkProcessConnection() void IPC::handleMessage<Messages::WebProcess::SetWebsiteDataStoreParameters, WebKit::WebProcess, void (WebKit::WebProcess::*)(WebKit::WebProcessDataStoreParameters&&)> IPC::Connection::dispatchMessage IPC::Connection::dispatchOneIncomingMessage WTF::RunLoop::performWork ... WebKit::XPCServiceMain ``` Since the main thread of the UIProcess is busy doing other things (like sending even more messages to WebProcess, building up its view hierarchy, committing a CATransaction, etc.), this sync IPC ends up blocking for 85 ms in the trace that I'm looking at. Importantly, it blocks the WebProcess from processing web page's LoadRequest method: ``` void IPC::handleMessage<Messages::WebPage::LoadRequest, WebKit::WebPage, void (WebKit::WebPage::*)(WebKit::LoadParameters&&)>(IPC::Decoder&, WebKit::WebPage*, void (WebKit::WebPage::*)(WebKit::LoadParameters&&)) IPC::MessageReceiverMap::dispatchMessage WebKit::WebProcess::didReceiveMessage IPC::Connection::dispatchMessage IPC::Connection::dispatchOneIncomingMessage WTF::RunLoop::performWork ... WebKit::XPCServiceMain(int, char const**) ``` WebProcess still seems to wait on UIProcess before it actually begins loading the main resource (since it waits for a policy decision from the UIProcess before doing so), but I think that removing the sync IPC will allow for better parallelization between UIProcess and WebProcess init during first-page-load scenarios and win us back some tens of ms.
Attachments
Patch (15.16 KB, patch)
2019-10-31 14:37 PDT, Ben Nham
no flags
Radar WebKit Bug Importer
Comment 1 2019-10-18 14:35:12 PDT
Ben Nham
Comment 2 2019-10-18 15:41:23 PDT
The UIProcess responds to the WebProcessProxy::GetNetworkProcessConnection message by turning around and sending a sync NetworkProcess::CreateNetworkConnectionToWebProcess message to NetworkProcess. So basically the sync call to WebProcessProxy::GetNetworkProcessConnection in WebProcess ends up blocking on the main threads of both UIProcess and NetworkProcess.
Chris Dumez
Comment 3 2019-10-19 15:36:21 PDT
This is about the webcontent process getting the ipc connection to the network process from the uiprocess. While this could be made async, this would require all call sites to ensureNetworkProcess() to deal this it be async. It is also unclear what the WebProcess would be able to do in the mean time. Pretty much the first thing it needs to do is schedule loads with the network process.
Ben Nham
Comment 4 2019-10-21 11:07:57 PDT
I think the idea would be to keep the sync ensureNetworkProcessConnection() code in there because that would be a pretty large refactoring. Instead maybe the UIProcess could change the init path when it picks a WebProcess out of the reuse pool. Perhaps it could give the WebProcess send rights to an already-running NetworkProcess so that the sync IPC becomes unnecessary in the common case.
Brady Eidson
Comment 5 2019-10-31 09:56:53 PDT
(In reply to Ben Nham from comment #4) > I think the idea would be to keep the sync ensureNetworkProcessConnection() > code in there because that would be a pretty large refactoring. Instead > maybe the UIProcess could change the init path when it picks a WebProcess > out of the reuse pool. Perhaps it could give the WebProcess send rights to > an already-running NetworkProcess so that the sync IPC becomes unnecessary > in the common case. NetworkProcess vending connections to itself is pretty engrained at this point. An idea would be for the UIProcess to always keep a spare NetworkToWebProcess connection around so it can always hand it directly off to the WebProcess.
Ben Nham
Comment 6 2019-10-31 14:37:29 PDT
Ben Nham
Comment 7 2019-10-31 14:42:22 PDT
In the attached patch, I went with one of Chris's ideas, which is to make setting the session ID on NetworkConnectionToWebProcess lazy. That way we can eagerly create that connection rather than waiting to create it in setWebsiteDataStoreParameters. On the plus side, this does remove two sync IPCs from first page load for a WebProcess in the common case. On the minus side, as I suspected, this doesn't actually make anything faster. This is because while WebProcess no longer blocks on sync IPC, it still is logically blocked waiting for the UIProcess to respond to the navigation delegate callback, which is handled on the UIProcess main thread. So for now the extra complexity in the patch is probably not worth it. I've still uploaded the patch in case we decide we want to revive it later on.
Note You need to log in before you can comment on or make changes to this bug.