New issue
Advanced search Search tips

Issue 671609 link

Starred by 4 users

Issue metadata

Status: Fixed
Owner:
Closed: Jul 2017
Cc:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 2
Type: Bug

Blocked on:
issue 368813
issue 732260



Sign in to add a comment

InterceptNavigationResourceThrottle delaying navigations on Android.

Project Member Reported by lizeb@chromium.org, Dec 6 2016

Issue description

On Android, navigations can be intercepted, to redirect to a native application for instance. The interception logic is in Java, and is executed on the UI thread.

For external navigations, the UI thread is usually busy in the early stages of a navigation. Since the throttle blocks the main resource request, this delay is highly likely to be on the critical path.

Attached is a trace taken with the following scenario:
- Nexus 5X, Android N
- Chrome master as of today (release)
- CustomTabsConnection#warmup() called, then 2s later the intent is sent. This maps to a Google Search-initiated navigation, for instance.
- Good WiFi

At offset 2230.806ms, *108ms* is spent waiting for this navigation throttle (from netlog). For this navigation, Navigation.StartToCommit is *550ms*, and the total main resource fetch time is *520ms*.

The delay is caused by queuing on the UI thread, since the actual throttle task executes for 
2.0ms (wall time) at offset 2337ms. The UI thread is typically tied for several 100s of ms after an external navigation, making the potential delays much higher.

 
trace.json.tar.gz
8.9 MB Download
Interesting find!

How prevalent is this interception logic? Does it happen for all navigations (i.e. we check all URLs against a list of native handlers)?

How typical is the delay?

In other words, do we have UMA? If not, would it be possible to add some?

Comment 2 by clamy@chromium.org, Dec 7 2016

It happens on all navigations and redirects. Technically the thread hop has been in place since forever: there used to be an InterceptResourceThrottle which was doing the same thread hop in the same case. The only difference with what used to be before is that we had to add an additional asynchronous check due to some issues in the tab destruction logic that would cause uaf bugs if we did synchronous checks.

I realize that I've been mistaken yesterday when Benoit and I spoke, the regression we observe when we introduced NavigationThrottles was on Windows, not on Android. This is because on Android the thread hop situation did not change: we introduced NavigationThrottles by transforming the InterceptResourceThrottle into an InterceptNavigationResourceThrottle. The version was synchronous at the time, we only made it asynchronous when we got uaf reports from the field. The change to asynchronous was only made later, when we got the uafs reports from the field. It was not picked up by bots, so I'm not sure how much of a delay this particular feature is causing.

The issue of the InterceptResourceThrottle itself delaying the navigation was already known when we started PlzNavigate. It'd be nice to see it improve though :).

Happily, the thread hop situation should become a bit better when PlzNavigate launches. Right now we have:
-> Browser UI thread: load url
-> Renderer: set up document loader & do request
-> Browser IO thread: set up request
-> Browser UI thread: NavigationThrottle::WillStartRequest
-> Browser IO thread: start network request
(if redirects:
-> Browser UI thread: NavigationThrottle::WillRedirectRequest
-> Browser IO thread: send IPC to renderer & wait for response
-> Renderer: check if redirect should be followed
-> Browser IO thread: follow redirect)
-> Browser UI thread: NavigationThrottle::WillProcessResponse
-> Browser IO thread: send response to renderer
-> Renderer: commit navigation

With PlzNavigate this becomes:
-> Browser UI thread: load url & NavigationThrottle::WillStartRequest
-> Browser IO thread: start network request
(if redirects:
-> Browser UI thread: NavigationThrottle::WillRedirectRequest which decides if redirect should be followed
-> Browser IO thread: follow redirect)
-> Browser UI thread: NavigationThrottle::WillProcessResponse & send stream endpoint to renderer
-> Renderer: request stream data
-> Browser IO thread: send stream data
-> Renderer: commit navigation

(Note that we plan to eventually get rid of the renderer requesting the stream in the end, but this requires significant changes to blink, so we're postponing that until later).

In any case, we should have a lot less hops, so this should be less of an issue. I think it'd be better to look at this issue once we have launched PlzNavigate, as the induced delay may be greatly reduced by the architectural change.

When it comes to timing NavigationThrottles, I've had this idea of imposing users of the class to add a name for their throttle and add histograms (Like FooNavigationThrottle::WillStartRequestTime for example) that the navigation code would record automatically each time it calls the throttles. This way we would have good & precise monitoring in the field. I've not had the time to push the idea yet, but it's been on my roadmap for better navigations for some time.
Thanks for the extra details, highly appreciated.

Agree on waiting after PlzNavigate.
Is issue 576261 the right bug to block on?

Comment 4 by clamy@chromium.org, Dec 8 2016

Blockedon: 368813
No we have a meta-bug in issue 368813. Adding it as a blocker.

Comment 5 by lizeb@chromium.org, Dec 8 2016

Re #1: About the delay, I expect it to be fully on the critical path for external intents coming from a well-behaved external app on Android. Google Search on Android is one of them. I can't give numbers on a public bug, but as you know, it's a large fraction of navigations.

For other navigations, the delay is likely much lower, as the UI thread is less likely to be busy.
Labels: -Performance -Performance-Startup Performance-Browser Performance-Loading

Comment 7 by lizeb@chromium.org, Jul 21 2017

Blockedon: 732260
Status: Fixed (was: Assigned)
Checking today, seems that it was solved in  crbug.com/732260 , which is fixed.

Yeah! \o/

Comment 8 by atua...@gmail.com, Dec 30 2017

In chrome 57, NavigationResourceThrottle::WillProcessResponse --> WillProcessResponseOnUIThread, this thread hop will cost more than 100ms in shouldInterceptRequest case, sometimes more than 500ms in low-end phone. shouldInterceptRequest is key interface for offline, so this thread hop cost will take badly affect for offline performance.

Sign in to add a comment