RESOLVED FIXED 237055
Preconnecting after process swap is a page load time improvement on some devices
https://bugs.webkit.org/show_bug.cgi?id=237055
Summary Preconnecting after process swap is a page load time improvement on some devices
Per Arne Vollan
Reported 2022-02-22 13:35:53 PST
Preconnecting after process swap is a page load time improvement on some devices, but a regression on others.
Attachments
Patch (2.78 KB, patch)
2022-02-22 13:46 PST, Per Arne Vollan
no flags
Patch (2.71 KB, patch)
2022-02-23 11:19 PST, Per Arne Vollan
no flags
Patch (10.67 KB, patch)
2022-03-03 10:03 PST, Per Arne Vollan
no flags
Patch (12.41 KB, patch)
2022-03-07 10:58 PST, Per Arne Vollan
no flags
Per Arne Vollan
Comment 1 2022-02-22 13:46:48 PST
Per Arne Vollan
Comment 2 2022-02-23 11:19:43 PST
Radar WebKit Bug Importer
Comment 3 2022-03-01 13:36:40 PST
Per Arne Vollan
Comment 4 2022-03-03 10:03:44 PST
Carlos Garcia Campos
Comment 5 2022-03-04 05:35:25 PST
Comment on attachment 453755 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=453755&action=review > Source/WebKit/ChangeLog:13 > + a second preconnect after the first has finished. It is important to wait until the first preconnect has > + finished, otherwise the second preconnect will go to waste, since the underlying network layer does not yet > + know if this is HTTP/1.1 or not. In the case of libsoup, if there's already a connection in idle state preconnect does nothing. So, this patch isn't useful for soup based ports, but it's harmless anyway. Maybe it's worth adding platform ifdefs, though.
Per Arne Vollan
Comment 6 2022-03-04 07:07:17 PST
(In reply to Carlos Garcia Campos from comment #5) > Comment on attachment 453755 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=453755&action=review > > > Source/WebKit/ChangeLog:13 > > + a second preconnect after the first has finished. It is important to wait until the first preconnect has > > + finished, otherwise the second preconnect will go to waste, since the underlying network layer does not yet > > + know if this is HTTP/1.1 or not. > > In the case of libsoup, if there's already a connection in idle state > preconnect does nothing. So, this patch isn't useful for soup based ports, > but it's harmless anyway. Maybe it's worth adding platform ifdefs, though. Ah, yes, that is a good point. I will update the patch. Thanks for reviewing!
Geoffrey Garen
Comment 7 2022-03-04 09:21:45 PST
> > In the case of libsoup, if there's already a connection in idle state > > preconnect does nothing. So, this patch isn't useful for soup based ports, > > but it's harmless anyway. Maybe it's worth adding platform ifdefs, though. > > Ah, yes, that is a good point. I will update the patch. Just a second: My understanding is that CFNetwork's behavior matches libsoup's behavior. But that doesn't invalidate the optimization. Our thesis is that the prior http/1.1 connection is usually not idle at the time of this preconnect. It is busy loading the main resource request. So, the expected effect of this preconnect is to "go wide" and open a second http/1.1 connection in parallel to downloading the main resource request on the first connection. Then we get a speedup because the second connection is ready to go with zero latency the moment we parse the first subresource request.
Geoffrey Garen
Comment 8 2022-03-04 09:24:52 PST
Comment on attachment 453755 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=453755&action=review > Source/WebKit/NetworkProcess/PreconnectTask.cpp:45 > +, m_timeoutTimer([this] { didFinish(ResourceError { String(), 0, m_networkLoad->parameters().request.url(), "Preconnection timed out"_s, ResourceError::Type::Timeout }, { }); }) Looks like the indentation got messed up here.
Geoffrey Garen
Comment 9 2022-03-04 09:33:12 PST
Perhaps a more principled way to write this optimization would explicitly arrange not to make the second preconnect request until the main resource request has been made (thereby guaranteeing that the first connection is not idle). Maybe we should test a change like that to see if it improves the optimization across more CPUs? I guess a way to do that would be for the UI process to initiate the first preconnect right when the navigation starts (as it does today), and then initiate the second preconnect right after we issue the load request for the main resource. Not sure exactly how to pipe the information that the connection is http/1.1 in this proposal -- maybe Per can figure out that piece.
Carlos Garcia Campos
Comment 10 2022-03-05 07:39:06 PST
(In reply to Geoffrey Garen from comment #7) > > > In the case of libsoup, if there's already a connection in idle state > > > preconnect does nothing. So, this patch isn't useful for soup based ports, > > > but it's harmless anyway. Maybe it's worth adding platform ifdefs, though. > > > > Ah, yes, that is a good point. I will update the patch. > > Just a second: My understanding is that CFNetwork's behavior matches > libsoup's behavior. But that doesn't invalidate the optimization. > > Our thesis is that the prior http/1.1 connection is usually not idle at the > time of this preconnect. It is busy loading the main resource request. So, > the expected effect of this preconnect is to "go wide" and open a second > http/1.1 connection in parallel to downloading the main resource request on > the first connection. Then we get a speedup because the second connection is > ready to go with zero latency the moment we parse the first subresource > request. The second preconnect is started right after the first one finishes right? I think it will be still idle at that point.
Per Arne Vollan
Comment 11 2022-03-07 10:58:45 PST
Per Arne Vollan
Comment 12 2022-03-07 11:02:00 PST
(In reply to Geoffrey Garen from comment #8) > Comment on attachment 453755 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=453755&action=review > > > Source/WebKit/NetworkProcess/PreconnectTask.cpp:45 > > +, m_timeoutTimer([this] { didFinish(ResourceError { String(), 0, m_networkLoad->parameters().request.url(), "Preconnection timed out"_s, ResourceError::Type::Timeout }, { }); }) > > Looks like the indentation got messed up here. Fixed in the latest patch. Thanks for reviewing!
Per Arne Vollan
Comment 13 2022-03-07 11:05:17 PST
(In reply to Geoffrey Garen from comment #9) > Perhaps a more principled way to write this optimization would explicitly > arrange not to make the second preconnect request until the main resource > request has been made (thereby guaranteeing that the first connection is not > idle). > > Maybe we should test a change like that to see if it improves the > optimization across more CPUs? > > I guess a way to do that would be for the UI process to initiate the first > preconnect right when the navigation starts (as it does today), and then > initiate the second preconnect right after we issue the load request for > the main resource. Not sure exactly how to pipe the information that the > connection is http/1.1 in this proposal -- maybe Per can figure out that > piece. Yes, this is a great idea. I think it would make sure that the second preconnect never goes to waste. I have started looking into this. Would you be OK with landing the current patch as-is, and then follow up with a new patch? The current patch seems to be a nice progression on macOS, at least on the devices that have been tested. Thanks for reviewing!
Per Arne Vollan
Comment 14 2022-03-07 11:08:26 PST
(In reply to Carlos Garcia Campos from comment #10) > (In reply to Geoffrey Garen from comment #7) > > > > In the case of libsoup, if there's already a connection in idle state > > > > preconnect does nothing. So, this patch isn't useful for soup based ports, > > > > but it's harmless anyway. Maybe it's worth adding platform ifdefs, though. > > > > > > Ah, yes, that is a good point. I will update the patch. > > > > Just a second: My understanding is that CFNetwork's behavior matches > > libsoup's behavior. But that doesn't invalidate the optimization. > > > > Our thesis is that the prior http/1.1 connection is usually not idle at the > > time of this preconnect. It is busy loading the main resource request. So, > > the expected effect of this preconnect is to "go wide" and open a second > > http/1.1 connection in parallel to downloading the main resource request on > > the first connection. Then we get a speedup because the second connection is > > ready to go with zero latency the moment we parse the first subresource > > request. > > The second preconnect is started right after the first one finishes right? I > think it will be still idle at that point. In the latest patch, finishedPreconnectForMainResource is called before starting the second preconnect. Calling finishedPreconnectForMainResource will in some cases start the load. Thanks for reviewing!
Geoffrey Garen
Comment 15 2022-03-07 11:41:01 PST
Comment on attachment 454003 [details] Patch r=me
Geoffrey Garen
Comment 16 2022-03-07 11:41:31 PST
> Would you be OK with landing the current patch as-is, and then follow up > with a new patch? Yup!
EWS
Comment 17 2022-03-07 18:13:55 PST
Committed r290969 (248148@main): <https://commits.webkit.org/248148@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 454003 [details].
Note You need to log in before you can comment on or make changes to this bug.