New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 904535 link

Starred by 1 user

Issue metadata

Status: Assigned
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: 2019-03-20
OS: Android
Pri: 2
Type: Bug



Sign in to add a comment

Potential jank caused by TouchDevice.availablePointerAndHoverTypes

Project Member Reported by ssid@chromium.org, Nov 12

Issue description

We collected slow reports from users facing janks and found that the function mentioned above is taking too much time on the main thread, potentially causing janks.
The issue can be found in reports:

bacedfcb70500d4d - 3994.477 ms (ui::MaxTouchPoints)
408ecff566e0545f - 985.953 ms (ui::MaxTouchPoints)

3bdc061a069e0928 - 352.648 ms (ui::AvailablePointerAndHoverTypes)
e119ac6ea0de977e - 313.711 ms (ui::AvailablePointerAndHoverTypes)
286a71661ff188cd - 301.241 ms (ui::AvailablePointerAndHoverTypes)
69385864d58d7352 - 212.701 ms (ui::AvailablePointerAndHoverTypes)

Go to crash/ReportID to view the traces.

The stack trace that was hit the most:

ioctl
<skipped java frames>
ui::MaxTouchPoints()
content::RenderViewHostImpl::OnWebkitPreferencesChanged()


__ioctl / malloc / lock / Unknown
<skipped java frames>
ui::AvailablePointerAndHoverTypes()
ui::GetAvailablePointerTypes()
ui::GetAvailablePointerAndHoverTypes()
content::RenderViewHostImpl::OnWebkitPreferencesChanged()
content::RenderViewHostImpl::GetWebkitPreferences()
content::RenderViewHostImpl::CreateRenderView(int, int, base::UnguessableToken const&, content::FrameReplicationState const&, bool)
content::WebContentsImpl::CreateRenderViewForRenderManager(content::RenderViewHost*, int, int, base::UnguessableToken const&, content::FrameReplicationState const&)
content::RenderFrameHostManager::InitRenderView(content::RenderViewHostImpl*, content::RenderFrameProxyHost*)
content::RenderFrameHostManager::ReinitializeRenderFrame(content::RenderFrameHostImpl*)
content::RenderFrameHostManager::GetFrameHostForNavigation(content::NavigationRequest const&)
content::RenderFrameHostManager::DidCreateNavigationRequest(content::NavigationRequest*)
content::FrameTreeNode::CreatedNavigationRequest(std::__ndk1::unique_ptr<content::NavigationRequest, std::__ndk1::default_delete<content::NavigationRequest> >)
content::NavigatorImpl::Navigate(std::__ndk1::unique_ptr<content::NavigationRequest, std::__ndk1::default_delete<content::NavigationRequest> >, content::ReloadType, content::RestoreType)
content::NavigationControllerImpl::NavigateToExistingPendingEntry(content::ReloadType)
 
Cc: bokan@chromium.org sadrul@chromium.org
RenderViewHostImpl::GetWebkitPreferences() is called on critical path to navigation and it turns out that the TouchDevice.java touches disk or takes lock. Most of the janks are caused when disk is slow on the device. Is there any way that we can continue navigation without reading this pref or taking the input device lock?
Cc: mustaq@chromium.org
Could we also cache this info, so that it doesn't get called for each page?
Because we want to cover dynamic scenarios (plugging in a mouse, for example) at least with page reload, caching would be acceptable if we have an Android API that notifies when input device changes.

I am surprised that ui::MaxTouchPoints takes so long, it seems to coming from a cached value already (InputDeviceClient::touchscreen_devices_), which is updated through InputDeviceClient::OnTouchscreenDeviceConfigurationChanged (https://cs.chromium.org/chromium/src/services/ws/public/cpp/input_devices/input_device_client.cc?rcl=a332fd8b08dd1f2d6e86f4e3fd550790bf91ba74&l=82).  Any chance this is not hooked up for Android?

The bottleneck for AvailablePointerAndHoverTypes seems to be Android InputDevice API which is used many times in the function:
https://cs.chromium.org/chromium/src/ui/android/java/src/org/chromium/ui/base/TouchDevice.java?rcl=747e3e8b8fd863770e396bc364873f62af02034c&l=57

Cc: smcgruer@chromium.org
According to smcgruer in [1] it should be possible to observe setting changes in Android [2]. IMHO, we should be caching the values at process startup and registering observers if we can.

[1] https://docs.google.com/document/d/1aZnSfg7I-xbRBYui5jkUIdbIgZ5jK9u-CUplPFU_tC8/view#
[2] https://developer.android.com/reference/android/database/ContentObserver
Components: Blink>Input
Stats:
The issue with ui::MaxTouchPoints() might just be package manager being really slow to respond. Sometimes system service might take locks and cause delays. There are few of these cases, but cause longer janks. whereas the availablePointerAndHoverTypes causes smaller delays, but seems to occur very frequently.
Owner: mustaq@chromium.org
Status: Assigned (was: Untriaged)
Mustaq, this seems like fairly low-hanging fruit. Could you take a look in the next few weeks?
Hmm, I don't think it's low hanging fruit because I still don't see any way to get notified about input device changes.

In particular, Android ContentObserver seems to be for catching changes in content, and I am not sure hardware plug-and-play cases are covered there.  	smcgruer@: any idea?

ssid@: "very frequently" => how frequently?  Perhaps we can shoot for a timer based solution (cache invalidates after a few minutes, say) to sacrifice a bit of live-hardware-update for sake of less jank.
Sorry, I am not an Android ContentObserver expert. My investigation was only for ANIMATOR_DURATION_SCALE for the prefers-reduced-media accessibility setting, I'm not sure why bokan@ added me here.

A naive google search points to https://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener as a possibility however, if you're wanting to listen to InputDevice changes.
Thanks smcgruer@ for the pointer, we seem to have a InputDeviceObserver based on that InputManager.
Cc: nyquist@chromium.org
Re #8: About 1.5% of the users have "RenderViewHostImpl::GetWebkitPrefs" trace event taking more than 100ms, just at startup. From stack samples most of the time spent in RenderViewHostImpl::GetWebkitPrefs() shows up in TouchDevice calls.

If you think this data is not detailed enough I could just add trace events across the TouchDevice calls to get more accurate stats about the time taken. if you think the fix for the issue is simple, then instead of trying to get better stats we could fix the issue. Let me know if you need more accurate metrics for the problem.

Also it looks like the caching will be useful from second navigation. Is there anyway to make the first navigation faster?
ssid@: The caching-like solution we discussed here would help only during calls made after initial one.
- Do we know if many calls are made after startup?
- Do we have any data on how frequently this happens (again after the initial one)?

RenderViewHostImpl::ComputeWebkitPrefs() is called pretty frequently. Almost all users have this function called more than once. About 25% of users have hit it more than twice in the first 30 seconds of startup.

Duration of the event at percentiles:
50th: 14ms
90th: 28 ms
95th: 45 ms
99th: 130 ms
I will take a look at this next week.

What I found so far is that availablePointerAndHoverTypes should already be checking dynamic device changes, as per crrev.comc/c/553457.  Not sure why the call still ends up on the Java side.
Status: Started (was: Assigned)
ssid@: Need a bit more info on #c13.  Do you see evidences of repeated back-to-back calls to "InputDeviceChangeObserver::NotifyRendererViewHost"?

---

I spotted a few possible redundancy problems in detection of dynamic device changes:

[Suspect] Not sure if Android InputDeviceListener [1] could be firing multiple times per input device change, or for phone orientation change.

[ClearlyBad] Once a device change is detected through InputDeviceObserver.java [2], we seem to be making multiple calls, one per device type [3] on the C++ side.  Each of them converge to a single method here [4].

[SomewhatBad] We have an unnecessary double-call to availablePointerAndHoverTypes() once a device change is detected: one direct call in [4], then another through
  [4]->OnWebkitPreferencesChanged()->ComputeWebkitPrefs().

---

[1] https://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener

[2] https://cs.chromium.org/chromium/src/ui/android/java/src/org/chromium/ui/events/devices/InputDeviceObserver.java?rcl=8de7f378da3c9a8e224ea9fa48d4906196e0003b&l=50&q=nativeInputConfigurationChanged

[3] https://cs.chromium.org/chromium/src/ui/events/devices/input_device_observer_android.cc?rcl=19fa17c7d4c41f5d2f943c1d99b08d3c6841f6ab&l=46

[4] https://cs.chromium.org/chromium/src/content/browser/renderer_host/input/input_device_change_observer.cc?rcl=19fa17c7d4c41f5d2f943c1d99b08d3c6841f6ab&l=58
Just confirmed that the [ClearlyBad] case in my last comment applies to page loads because OnWebkitPreferencesChanged() is called at least twice during load:
- via RenderFrameHostManager::InitRenderView(), and then
- via InputDeviceChangeObserver::NotifyRenderViewHost().

So fixing the [ClearlyBad] case should help with load performance.
Looks like #c16 is desktop only.  On Android, NotifyRenderViewHost is not even called on startup.

Project Member

Comment 18 by bugdroid1@chromium.org, Dec 13

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/950777f59395500bb893d184fadfecc5883f03df

commit 950777f59395500bb893d184fadfecc5883f03df
Author: Mustaq Ahmed <mustaq@google.com>
Date: Thu Dec 13 19:15:43 2018

Enable InputDeviceEventObserver to receive batched updates.

On Android, we had a single system call forking into three different
InputDeviceEventObserver calls, which resulted in redundant updates in
InputDeviceChangeObserver.  Batching multiple device updates into one avoids the
redundancy.

Bug: 904535
Change-Id: I04a56db23553ae2d1cbe97fffd97d03189665187
Reviewed-on: https://chromium-review.googlesource.com/c/1363636
Commit-Queue: Mustaq Ahmed <mustaq@chromium.org>
Reviewed-by: Navid Zolghadr <nzolghadr@chromium.org>
Reviewed-by: Michael Spang <spang@chromium.org>
Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org>
Cr-Commit-Position: refs/heads/master@{#616385}
[modify] https://crrev.com/950777f59395500bb893d184fadfecc5883f03df/content/browser/renderer_host/input/input_device_change_observer.cc
[modify] https://crrev.com/950777f59395500bb893d184fadfecc5883f03df/content/browser/renderer_host/input/input_device_change_observer.h
[modify] https://crrev.com/950777f59395500bb893d184fadfecc5883f03df/ui/events/devices/input_device_event_observer.h
[modify] https://crrev.com/950777f59395500bb893d184fadfecc5883f03df/ui/events/devices/input_device_observer_android.cc
[modify] https://crrev.com/950777f59395500bb893d184fadfecc5883f03df/ui/events/devices/input_device_observer_android.h

Project Member

Comment 19 by bugdroid1@chromium.org, Jan 16

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/b550d48c93c7f489be027c86463b49867b041b4b

commit b550d48c93c7f489be027c86463b49867b041b4b
Author: Mustaq Ahmed <mustaq@google.com>
Date: Wed Jan 16 00:08:40 2019

Optimize updates to WebPreferences fields that are slow to recompute.

Some values in |WebPreferences| are slow to compute because they
are related to low-level hardware changes.  They are bad
particularly on Android: the calls go through JNI interfaces
then even cause system level locks in certain cases.

Even worse is the fact that |RVH::OnWebkitPreferencesChanged|
(which triggers the recomputation) is called multiple times during a
page load, for various non-hardware-related preference updates.  On
Android, the repeated computation of the slow values added hundreds
of milliseconds to load times.

This CL avoids blind recomputation of the slow values, by reusing
the cached result for any call to |RVH::OnWebkitPreferencesChanged|
that is known to be independent of hardware-changes.

Bug: 904535
Change-Id: I3bac25af516ae7ed52770d4cd5d08bda5ec75e3b
Reviewed-on: https://chromium-review.googlesource.com/c/1377148
Reviewed-by: Gabriel Charette <gab@chromium.org>
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
Reviewed-by: Ken Buchanan <kenrb@chromium.org>
Commit-Queue: Mustaq Ahmed <mustaq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#622899}
[modify] https://crrev.com/b550d48c93c7f489be027c86463b49867b041b4b/chrome/browser/prefs/chrome_pref_service_unittest.cc
[modify] https://crrev.com/b550d48c93c7f489be027c86463b49867b041b4b/content/browser/frame_host/mixed_content_navigation_throttle.cc
[modify] https://crrev.com/b550d48c93c7f489be027c86463b49867b041b4b/content/browser/frame_host/mixed_content_navigation_throttle.h
[modify] https://crrev.com/b550d48c93c7f489be027c86463b49867b041b4b/content/browser/renderer_host/input/input_device_change_observer.cc
[modify] https://crrev.com/b550d48c93c7f489be027c86463b49867b041b4b/content/browser/renderer_host/input/input_device_change_observer.h
[modify] https://crrev.com/b550d48c93c7f489be027c86463b49867b041b4b/content/browser/renderer_host/input/interaction_mq_dynamic_browsertest.cc
[modify] https://crrev.com/b550d48c93c7f489be027c86463b49867b041b4b/content/browser/renderer_host/render_view_host_impl.cc
[modify] https://crrev.com/b550d48c93c7f489be027c86463b49867b041b4b/content/browser/renderer_host/render_view_host_impl.h
[modify] https://crrev.com/b550d48c93c7f489be027c86463b49867b041b4b/content/public/browser/render_view_host.h
[modify] https://crrev.com/b550d48c93c7f489be027c86463b49867b041b4b/content/public/test/test_renderer_host.h
[modify] https://crrev.com/b550d48c93c7f489be027c86463b49867b041b4b/content/test/test_render_view_host.cc
[modify] https://crrev.com/b550d48c93c7f489be027c86463b49867b041b4b/content/test/test_render_view_host.h

Comment 20 by mustaq@chromium.org, Jan 16 (6 days ago)

ssid@: The fix we landed should decrease the delay significantly.  How long would it take to get updated reports?  I guess we have to wait for beta/stable, right?

Comment 21 by mustaq@chromium.org, Jan 18 (4 days ago)

NextAction: 2019-03-20
Status: Assigned (was: Started)

Comment 22 by ssid@chromium.org, Jan 19 (4 days ago)

There is an issue with tracing and the system is broken for a week now. I will follow up on this bug as soon as it's fixed.

Sign in to add a comment