-
Notifications
You must be signed in to change notification settings - Fork 6
TTI
Time to interactive (TTI) is a time in milliseconds (ms) spent since the screen's creation starts until the first frame of meaningful content is rendered, ensuring that:
- All internal setup is ready
- UI is layout and rendered
- Most important data has arrived and is shown to user
- Main thread is ready to process incoming events
TTI always includes native app performance, and also may depend on the network performance. This metrics allow us to monitor how fast user can actually start using the screen in its main purpose.
See also:
Time To First Render (TTFR) is a time in milliseconds (ms) spent since the screen's creation starts until the screen renders its first frame.
It starts at the same time as general TTI measurement, but may stop earlier. In the most common case screen should be ready to be drawn as soon as possible, but it shouldn't necessarily show meaningful content immediately. Usually screen can show some "pre-loader" and do some heavy initializations in the background. We stop TTFR tracking once the very first frame is drawn so the metric is pretty close to measuring screen's creation time. It allows us to prevent UI thread from freezing on creation which comes with better user experience.
This metric directly impacts TTI and may impact Rendering Performance.
Implement TTIMetricsReceiver
to receive TTI events for your view controllers.
If you track TTI for your screen: explicitly call screenIsReady()
in your view controller when it is completely usable (data loaded and displayed). If you do not call this method, screen is considered usable by default after viewDidAppear
is called.
The moment of the screen becoming usable should be wisely defined by the developer.
Also, it is always important to carefully maintain the correctness of TTI tracking on the client (e.g. when screen's UI/UX is changed, or refactoring made, or any changes made in screen's initialization process).
If you screen is purely on SwiftUI you usually still have your own subclass of UIHostingController
. If you can't call screenIsReady
method from the view controller, because you don't have the reference to the view controller from your SwiftUI view, you can use screenIsReadyOnAppear
extension in your SwiftUI view:
var body: some View {
if viewModel.isLoading {
ProgressView()
} else {
Text("Screen is ready").screenIsReadyOnAppear()
}
}
All TTI tracking works on the UIViewController
level. If you want to track TTI for some part of code without corresponding UIViewController
, for example for a separate banner or a separate row of the screen, you can use fragment TTI tracking. This works manually: you call PerformanceMonitoring.startFragmentTTI(screen:)
, which returns you an object. And when ready, you call method fragmentIsRendered
to stop TTFR (not mandatory) and fragmentIsReady
to stop TTI.
self.trackable = try? PerformanceMonitoring.startFragmentTTI(screen: .geniusVipFragmentBookingDetails)
...
if hasDataToShow {
self.trackable?.fragmentIsReady()
}