Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Do not call Animator::Delegate::OnAnimatorNotifyIdle until at least one frame has been rendered. #29015

Merged
merged 5 commits into from
Oct 7, 2021

Conversation

dnfield
Copy link
Contributor

@dnfield dnfield commented Oct 5, 2021

Otherwise, the animator may get started by a number of events (e.g. getting an onscreen surface created) and notify Dart that we're idle when we are in fact working dutifully to get to the first frame.

Fixes flutter/flutter#91209

This significantly improves customer: money's start up time by avoiding GC work before the first frame. Per @zanderso , we may also want some way to tell dart to size the heap appropriately to avoid unnecessary work to grow it early in the application as well.

@zanderso
Copy link
Member

zanderso commented Oct 5, 2021

The new test is segfaulting.

@dnfield
Copy link
Contributor Author

dnfield commented Oct 5, 2021

Ah. I only ran it locally with debug unoptimized. I'll check profile out.

@dnfield
Copy link
Contributor Author

dnfield commented Oct 5, 2021

Issue was that the animator was sometimes getting deleted before the vsync waiter was trying to check a callback the animator ends up deleting in its dtor. The engine seems to handle this correctly. I refactored the test to more carefully control vsync pulses, found a flake where I was sometimes losing a race to the delayed task for notify idle in BeginFrame, and made sure to stop/flush the animator before deleting it.

@dnfield
Copy link
Contributor Author

dnfield commented Oct 5, 2021

This is now ready for review.

@dnfield
Copy link
Contributor Author

dnfield commented Oct 6, 2021

And big thanks to @bdero for getting asan builds working for this - without that it would've been really hard to figure out what's going on here.

@zanderso
Copy link
Member

zanderso commented Oct 6, 2021

Do we have a benchmark that runs on our CI that will show a benefit from this change? (And which more importantly will regress if the effects of this change are broken).

@dnfield
Copy link
Contributor Author

dnfield commented Oct 6, 2021

I don't think so. Looking at the traces for flutter_gallery__start_up, it doesn't typically run into this problem because it tends to very quickly get to runApp, so there's not really much time for the animator to send the wrong signals.

We could add a test to our CI that does something like try to talk to some plugins before runApp, or just does an await Future.delayed or something, but the internal customer does have tests that would benefit from this.

@zanderso
Copy link
Member

zanderso commented Oct 6, 2021

but the internal customer does have tests that would benefit from this.

It creates a bit of disruption and makes customers unhappy when we don't discover regressions until downstream post-submit benchmarks run. If there's anything we can do to prevent that situation, then I think it's worth the trouble.

@dnfield
Copy link
Contributor Author

dnfield commented Oct 6, 2021

flutter/flutter#91346

@dnfield
Copy link
Contributor Author

dnfield commented Oct 6, 2021

Performance test has landed downstream. Anyone up for reviewing this? :)

Copy link
Member

@zanderso zanderso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm w/ cleanup suggestion.

@@ -147,7 +147,7 @@ void Animator::BeginFrame(
delegate_.OnAnimatorBeginFrame(frame_target_time, frame_number);
}

if (!frame_scheduled_) {
if (!frame_scheduled_ && has_rendered_) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know what the magic number 100000 down on line 172 is for? Sorry it isn't part of your PR, but if you're in the neighborhood and you know what it is and why it has that value, could you make a constant for it and document it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK this was done by some Fuchsia folks to try to avoid kicking off a GC when we're about to animate. I'm not sure where it came from though, and it's not well tested.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it's to make up for the fact that we just delayed 51ms but I'm really not sure. I'm going to land this as-is, and if Nathan knows what's up maybe we can add more docs there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh ok thanks Jason

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The magic number "100ms" was meant to be enough time to run the compactor but not so much time that things wouldn't be awful if we've incorrectly detected idle time. 100ms probably isn't enough time for slower devices or larger heaps. This logic should probably be moved to the engine's task runners / scheduler to properly detect idle time, and invoke Dart_NotifyIdle with a much further deadline.

@dnfield dnfield merged commit c871051 into flutter:master Oct 7, 2021
@dnfield dnfield deleted the engine_idle branch October 7, 2021 16:42
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 7, 2021
fluttergithubbot pushed a commit to flutter/flutter that referenced this pull request Oct 7, 2021
clocksmith pushed a commit to clocksmith/flutter that referenced this pull request Oct 29, 2021
yx-mike added a commit to yx-mike/engine that referenced this pull request Jan 12, 2022
Do not call Animator::Delegate::OnAnimatorNotifyIdle until at least one frame has been rendered. (flutter#29015)
yx-mike added a commit to yx-mike/engine that referenced this pull request Jan 18, 2022
Do not call Animator::Delegate::OnAnimatorNotifyIdle until at least one frame has been rendered. (flutter#29015)

flutter/flutter#91209
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Animator started unpaused and can distract from work leading to first frame
4 participants