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

Issue 764524 link

Starred by 1 user

Issue metadata

Status: WontFix
Owner: ----
Closed: Jan 2018
Cc:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 3
Type: Bug

Blocking:
issue 735799



Sign in to add a comment

Investigate first measure/layout/draw events

Project Member Reported by dskiba@chromium.org, Sep 12 2017

Issue description

I was always curious about strange sequence of Looper.dispatchMessage events that don't run Chrome tasks.

In the attached screenshot (trace.html from crbug.com/735799#c31) three Looper.dispatchMessage take 211ms.

I ran tracing with gfx,view,wm categories and found that those Looper events seem to correspond to animator:translationZ animation. See screenshot and attached trace.


Do we know who is responsible for this animation?
 
LooperEvents.png
39.9 KB View Download
animation.png
75.0 KB View Download
gfx-view-wm.html.gz
1.3 MB Download

Comment 1 by dskiba@chromium.org, Sep 12 2017

Blocking: 735799

Comment 2 by dskiba@chromium.org, Sep 13 2017

Cc: mariakho...@chromium.org

Comment 3 by dskiba@chromium.org, Sep 13 2017

Found the culprit: 

main[1] print getNameForTrace()
 getNameForTrace() = "animator:translationZ"
main[1] where
  [1] android.animation.ValueAnimator.startAnimation (ValueAnimator.java:1,225)
  [2] android.animation.ValueAnimator.start (ValueAnimator.java:1,041)
  [3] android.animation.ValueAnimator.start (ValueAnimator.java:1,065)
  [4] android.animation.ObjectAnimator.start (ObjectAnimator.java:852)
  [5] android.animation.ValueAnimator.startWithoutPulsing (ValueAnimator.java:1,058)
  [6] android.animation.AnimatorSet.handleAnimationEvents (AnimatorSet.java:1,142)
  [7] android.animation.AnimatorSet.startAnimation (AnimatorSet.java:1,227)
  [8] android.animation.AnimatorSet.start (AnimatorSet.java:729)
  [9] android.animation.AnimatorSet.start (AnimatorSet.java:684)
  [10] android.animation.StateListAnimator.start (StateListAnimator.java:188)
  [11] android.animation.StateListAnimator.setState (StateListAnimator.java:181)
  [12] android.view.View.drawableStateChanged (View.java:19,990)
  [13] android.widget.TextView.drawableStateChanged (TextView.java:4,969)
  [14] org.chromium.chrome.browser.widget.newtab.NewTabButton.drawableStateChanged (NewTabButton.java:54)
  [15] android.view.View.refreshDrawableState (View.java:20,045)
  [16] android.view.View.dispatchAttachedToWindow (View.java:17,437)
  [17] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [18] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [19] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [20] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [21] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [22] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [23] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [24] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [25] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [26] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [27] android.view.ViewRootImpl.performTraversals (ViewRootImpl.java:1,668)
  [28] android.view.ViewRootImpl.doTraversal (ViewRootImpl.java:1,392)
  [29] android.view.ViewRootImpl$TraversalRunnable.run (ViewRootImpl.java:6,752)
  [30] android.view.Choreographer$CallbackRecord.run (Choreographer.java:911)
  [31] android.view.Choreographer.doCallbacks (Choreographer.java:723)
  [32] android.view.Choreographer.doFrame (Choreographer.java:658)
  [33] android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:897)
  [34] android.os.Handler.handleCallback (Handler.java:790)
  [35] android.os.Handler.dispatchMessage (Handler.java:99)
  [36] android.os.Looper.loop (Looper.java:164)
  [37] android.app.ActivityThread.main (ActivityThread.java:6,494)
  [38] java.lang.reflect.Method.invoke (native method)
  [39] com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:438)
  [40] com.android.internal.os.ZygoteInit.main (ZygoteInit.java:807)


Actually, NewTabButton starts one more animation before that:

main[1] print getNameForTrace()
 getNameForTrace() = "animator:elevation"
main[1] where
  [1] android.animation.ValueAnimator.startAnimation (ValueAnimator.java:1,225)
  [2] android.animation.ValueAnimator.start (ValueAnimator.java:1,041)
  [3] android.animation.ValueAnimator.start (ValueAnimator.java:1,065)
  [4] android.animation.ObjectAnimator.start (ObjectAnimator.java:852)
  [5] android.animation.ValueAnimator.startWithoutPulsing (ValueAnimator.java:1,058)
  [6] android.animation.AnimatorSet.handleAnimationEvents (AnimatorSet.java:1,142)
  [7] android.animation.AnimatorSet.startAnimation (AnimatorSet.java:1,227)
  [8] android.animation.AnimatorSet.start (AnimatorSet.java:729)
  [9] android.animation.AnimatorSet.start (AnimatorSet.java:684)
  [10] android.animation.StateListAnimator.start (StateListAnimator.java:188)
  [11] android.animation.StateListAnimator.setState (StateListAnimator.java:181)
  [12] android.view.View.drawableStateChanged (View.java:19,990)
  [13] android.widget.TextView.drawableStateChanged (TextView.java:4,969)
  [14] org.chromium.chrome.browser.widget.newtab.NewTabButton.drawableStateChanged (NewTabButton.java:54)
  [15] android.view.View.refreshDrawableState (View.java:20,045)
  [16] android.view.View.dispatchAttachedToWindow (View.java:17,437)
  [17] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [18] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [19] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [20] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [21] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [22] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [23] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [24] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [25] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [26] android.view.ViewGroup.dispatchAttachedToWindow (ViewGroup.java:3,333)
  [27] android.view.ViewRootImpl.performTraversals (ViewRootImpl.java:1,668)
  [28] android.view.ViewRootImpl.doTraversal (ViewRootImpl.java:1,392)
  [29] android.view.ViewRootImpl$TraversalRunnable.run (ViewRootImpl.java:6,752)
  [30] android.view.Choreographer$CallbackRecord.run (Choreographer.java:911)
  [31] android.view.Choreographer.doCallbacks (Choreographer.java:723)
  [32] android.view.Choreographer.doFrame (Choreographer.java:658)
  [33] android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:897)
  [34] android.os.Handler.handleCallback (Handler.java:790)
  [35] android.os.Handler.dispatchMessage (Handler.java:99)
  [36] android.os.Looper.loop (Looper.java:164)
  [37] android.app.ActivityThread.main (ActivityThread.java:6,494)
  [38] java.lang.reflect.Method.invoke (native method)
  [39] com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:438)
  [40] com.android.internal.os.ZygoteInit.main (ZygoteInit.java:807)




Comment 4 by dskiba@chromium.org, Sep 13 2017

Both of those animations are button_state_list_anim_material, set as "stateListAnimator" in "Widget.Material.Button".

main[1] where
  [1] android.view.View.setStateListAnimator (View.java:14,783)
  [2] android.view.View.<init> (View.java:5,048)
  [3] android.widget.TextView.<init> (TextView.java:826)
  [4] android.widget.Button.<init> (Button.java:166)
  [5] android.widget.Button.<init> (Button.java:141)
  [6] android.widget.Button.<init> (Button.java:117)
  [7] org.chromium.chrome.browser.widget.newtab.NewTabButton.<init> (NewTabButton.java:1)
  [8] java.lang.reflect.Constructor.newInstance0 (native method)
  [9] java.lang.reflect.Constructor.newInstance (Constructor.java:334)
  [10] android.view.LayoutInflater.createView (LayoutInflater.java:647)
  [11] android.view.LayoutInflater.createViewFromTag (LayoutInflater.java:790)
  [12] android.view.LayoutInflater.createViewFromTag (LayoutInflater.java:730)
  [13] android.view.LayoutInflater.rInflate (LayoutInflater.java:863)
  [14] android.view.LayoutInflater.parseInclude (LayoutInflater.java:963)
  [15] android.view.LayoutInflater.rInflate (LayoutInflater.java:859)
  [16] android.view.LayoutInflater.rInflateChildren (LayoutInflater.java:824)
  [17] android.view.LayoutInflater.inflate (LayoutInflater.java:515)
  [18] android.view.LayoutInflater.inflate (LayoutInflater.java:423)
  [19] android.view.ViewStub.inflateViewNoAdd (ViewStub.java:269)
  [20] android.view.ViewStub.inflate (ViewStub.java:302)
  [21] org.chromium.chrome.browser.toolbar.ToolbarControlContainer.initWithToolbar (ToolbarControlContainer.java:49)
  [22] org.chromium.chrome.browser.ChromeActivity.setContentView (ChromeActivity.java:180)
  [23] org.chromium.chrome.browser.init.AsyncInitializationActivity.setContentViewAndLoadLibrary (AsyncInitializationActivity.java:28)
  [24] org.chromium.chrome.browser.init.ChromeBrowserInitializer.handlePreNativeStartup (ChromeBrowserInitializer.java:77)
  [25] org.chromium.chrome.browser.init.AsyncInitializationActivity.onCreate (AsyncInitializationActivity.java:111)

Comment 5 by dskiba@chromium.org, Sep 13 2017

I can get rid of animation by calling setStateListAnimator(null) in NewTabButton ctor, but that doesn't help with those events. It looks like we're rendering our UI hierarchy there, measuring it for the first time. I.e. we need to simplify UI to cut that down.
When you say the animation doesn't help with those events, are you saying removing the animator doesn't give any benefit?

Should we instead just change this bug to be something like "lazily inflate new tab button on startup"?

I don't think we'd want to set the Animator to null anyway.  I think we could try to just have it call jumpToCurrentState in the constructor to get rid of the animation call.
Summary: Investigate first measure/layout/draw events (was: animator:translationZ animation during startup (low-end))
I've taken method trace between ChromeApplication.onCreate and ChromeBrowserInitializer.startChromeBrowserProcessesAsync, so it includes the events this bug is concerned about.

One interesting thing I can see is that hierarchy is measured twice during the invocation of ViewRootImpl.performTraversals():

* First from ViewRootImpl.measureHierarchy() -> ViewRootImpl.performMeasure().

* Second time ViewRootImpl.performMeasure() is called directly by performTraversals(), and that's likely happens here [1]. Note that there is an optional log that hints that this situation is not common ("Ooops, something changed!").

I think we need to dig deeper here to understand why we're measuring for the second time.



[1] https://android.googlesource.com/platform/frameworks/base/+/oreo-release/core/java/android/view/ViewRootImpl.java#2155

firstevents.trace.gz
3.5 MB Download
I added instrumentation and found that first time measure() is called with

"width: {MeasureSpec: EXACTLY 480}, height: {MeasureSpec: EXACTLY 746}"

and the second time it's called with

"width: {MeasureSpec: EXACTLY 480}, height: {MeasureSpec: EXACTLY 854}"

Any idea why height changed? Seem that the second time height includes the status bar?

Comment 9 by dskiba@chromium.org, Nov 23 2017

Labels: -Performance-Loading Performance-Startup
Status: WontFix (was: Untriaged)
I tried disabling animations and didn't see any change, see here: https://docs.google.com/document/d/1OAd1fYv2ugUaiLOTnBPtebNsfvzKaxA-aQVeasmQ6dA/edit#heading=h.scgi3ifyuop2

Sign in to add a comment