Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TTID & TTFD for navigating between screens #1780

Closed
buenaflor opened this issue Dec 11, 2023 · 4 comments
Closed

TTID & TTFD for navigating between screens #1780

buenaflor opened this issue Dec 11, 2023 · 4 comments

Comments

@buenaflor
Copy link
Contributor

Description

Implement:

  • TTID (Time to Initial Display) - for a screen, the time it takes to load the minimally interactive state (background, navigation, fast loading local content)

  • TTFD (Time to Full Display) - for a screen, the time it takes to completely render the screen, including content from disk/network

TTID:

  • enabled by default

TTFD:

  • disabled by default
  • opt-in with 30 seconds timeout where the span finishes with deadline exceeded
  • manually reported by user with Sentry.reportFullyDisplayed()
@ueman
Copy link
Collaborator

ueman commented Dec 11, 2023

This TTID and TTID metric collection is a bit tricky with Flutter since it doesn't have similar concept to Androids Activity or iOS' ViewController. In Flutter it's just widget. Changing "screen"s is just rebuilding a widget, but widgets don't work like Activities or ViewControllers and you basically can't do heavy work in them. Since it's all widgets you don't really have a starting point from where to start measuring TTID and TTFD.

Therefore, the only time those metrics are actually helpful is during the app startup, not during screen changes.

The first frame is drawn when the first endOfFrame future finished. (Related https://api.flutter.dev/flutter/scheduler/SchedulerBinding/scheduleWarmUpFrame.html)

However, you can manually defer drawing of the first frame via https://api.flutter.dev/flutter/rendering/RendererBinding/deferFirstFrame.html together with https://api.flutter.dev/flutter/rendering/RendererBinding/allowFirstFrame.html

Hooking into those methods is possible via custom widgetsbinding (I did play around with that for measuring methodchannel, so I can give you some pointers if interested). Ultimately, I kinda question whether the metrics are actually useful for Flutter since they're probably virtually identical to the app start metrics, or at least very similar.

@marandaneto
Copy link
Contributor

If it's done right, it still makes sense IMO, eg when a new route is called, it's technically a new widget/screen.

The question is if it's possible to determine the very first frame drawn on that route for properly measuring TTID (without a delay, will need a callback that is executed right away after the frame is drawn).

The other thing to figure out is that the routing methods are non-async methods and you can't await the calls nor wrap the methods in a Future in the observer, so the timing isn't always accurate because when you request a new route, most of the time is executed right away if the event loop isn't busy, but if it is, it might execute a few milliseconds later, and the ttid/ttfd is already off by a bit, today this problem already exists with the current transactions in the sentry observer IIRC.

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 Dec 12, 2023
@buenaflor buenaflor changed the title TTID & TTID for navigating between screens TTID & TTFD for navigating between screens Dec 12, 2023
@buenaflor
Copy link
Contributor Author

Would using WidgetsBinding.instance.addPostFrameCallback in didPush be able to approximate a measurement?

afaik didPush is called after the page is pushed into the navigation stack so we might lose a couple milliseconds if we start the measurement in didPush.

Doesn't solve the potential event loop delays but it might be a direction we can look into for the callback.

@marandaneto
Copy link
Contributor

Would using WidgetsBinding.instance.addPostFrameCallback in didPush be able to approximate a measurement?

@denrase and I played a bit with that, we also used it for app start, but it's a global callback, and not per screen, so you might get the wrong callback and assume it's the one you want (just a hunch).

afaik didPush is called after the page is pushed into the navigation stack so we might lose a couple milliseconds if we start the measurement in didPush.

didPush is a sync method, but Sentry's start transaction isn't (maybe it can be now?), so you have to go around that too.

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 Dec 12, 2023
@buenaflor buenaflor added the flutter flutter label Dec 12, 2023
@buenaflor buenaflor moved this from Needs Investigation to In Progress in Mobile & Cross Platform SDK Feb 6, 2024
@buenaflor buenaflor moved this from In Progress to Needs Review in Mobile & Cross Platform SDK Mar 7, 2024
@buenaflor buenaflor moved this from Needs Review to Done in Mobile & Cross Platform SDK Mar 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Archived in project
Development

No branches or pull requests

4 participants