Mobile Vitals
Quality signals for mobile development, inspired by Web Vitals. Helping app developers deliver a great mobile user experience, regardless of whether you're building for iOS or Android.
We've used benchmarks collected from real-world applications to help set goals for these metrics. Answering the question, "what *is* a good experience on my platform?"
The Metrics
Cold Start
The time it takes a mobile application to start either immediately after booting, or after the application has been killed or evicted from memory.
Why is this important?
Cold Start represents a user's first experience with your application. Make a good first impression.
How to Measure
// Android Cold Start Measurement - Hello World Placeholder
// TODO: Replace with actual implementation for your app
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// TODO: Add your cold start measurement code here
// Example: Use Trace API, System.currentTimeMillis(), or Android Studio Profiler
// Reference: https://developer.android.com/topic/performance/vitals/launch-time
Log.d("ColdStart", "Hello World - Add your measurement code here!");
}
}
Thresholds
How to Measure
// iOS Cold Start Measurement - Hello World Placeholder
// TODO: Replace with actual implementation for your app
import os.log
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// TODO: Add your cold start measurement code here
// Example: Use CFAbsoluteTimeGetCurrent(), Xcode Instruments, or os_log
// Reference: https://developer.apple.com/documentation/xcode/reducing-your-app-s-launch-time
print("Hello World - Add your measurement code here!")
return true
}
}
Thresholds
Warm Start
Warm Starts measure how long it takes your application to start when some combination of state and resources is already available in memory. Warm start measures a spectrum of behaviour, as it depends on what resources are available, vs., what's been evicted.
Why is this important?
Your users will frequently not be launching your application from scratch. Slow Warm Start performance will contribute to bad perceived performance over time.
How to Measure
// Android Warm Start Measurement - Hello World Placeholder
// TODO: Replace with actual implementation for your app
public class MainActivity extends AppCompatActivity {
@Override
protected void onResume() {
super.onResume();
// TODO: Add your warm start measurement code here
// Example: Use System.currentTimeMillis(), onResume timing, or Android Studio Profiler
// Reference: https://developer.android.com/topic/performance/vitals/launch-time
Log.d("WarmStart", "Hello World - Add your measurement code here!");
}
}
Thresholds
How to Measure
// iOS Warm Start Measurement - Hello World Placeholder
// TODO: Replace with actual implementation for your app
class AppDelegate: UIResponder, UIApplicationDelegate {
func applicationWillEnterForeground(_ application: UIApplication) {
// TODO: Add your warm start measurement code here
// Example: Use CFAbsoluteTimeGetCurrent(), applicationWillEnterForeground, or Xcode Instruments
// Reference: https://developer.apple.com/documentation/xcode/reducing-your-app-s-launch-time
print("Hello World - Add your measurement code here!")
}
}
Thresholds
Time to Initial Display
The time it takes your application, either from a cold or warm start, to render its first frame of animation to screen.
Why is this important?
This metric is a good indicator of when your user perceives your application as having actually launched.
How to Measure
// Android Time to Initial Display - Hello World Placeholder
// TODO: Replace with actual implementation for your app
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// TODO: Add your initial display measurement code here
// Example: Use FrameMetrics API, GPU Info, or Android Studio Profiler
// Reference: https://developer.android.com/topic/performance/vitals/launch-time#time-initial
Log.d("InitialDisplay", "Hello World - Add your measurement code here!");
}
}
Thresholds
How to Measure
// iOS Time to Initial Display - Hello World Placeholder
// TODO: Replace with actual implementation for your app
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// TODO: Add your initial display measurement code here
// Example: Use CADisplayLink, Xcode Instruments, or Core Animation profiling
// Reference: https://developer.apple.com/documentation/xcode/reducing-your-app-s-launch-time#Track-additional-startup-activities
print("Hello World - Add your measurement code here!")
}
}
Thresholds
Time to Full Display
The time it takes your application to actually become useable.
Why is this important?
If additional work, e.g., rendering a document, needs to happen before your application becomes useable, this will contribute to your users perceived performance.
How to Measure
// Android Time to Full Display - Hello World Placeholder
// TODO: Replace with actual implementation for your app
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// TODO: Add your full display measurement code here
// Example: Use ViewTreeObserver, layout completion listeners, or Android Studio Profiler
// Reference: https://developer.android.com/topic/performance/vitals/launch-time#time-full
Log.d("FullDisplay", "Hello World - Add your measurement code here!")
}
}
Thresholds
How to Measure
// iOS Time to Full Display - Hello World Placeholder
// TODO: Replace with actual implementation for your app
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// TODO: Add your full display measurement code here
// Example: Use viewDidLayoutSubviews, layout completion, or Xcode Instruments
// Reference: https://developer.apple.com/documentation/xcode/reducing-your-app-s-launch-time#Track-additional-startup-activities
print("Hello World - Add your measurement code here!")
}
}
Thresholds
Frame Delay
When a user interacts with your application, the next frame of animation should render in a reasonable amount of time and, the app falling back into a responsive state. Frame delay is a spectrum, slow frames feel janky, where as truly frozen frames can result in an application feeling unresponsive or hung.
Why is this important?
A janky or frozen application feels unstable and, in general, is a bad user experience.
How to Measure
// Android Frame Delay Measurement - Hello World Placeholder
// TODO: Replace with actual implementation for your app
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// TODO: Add your frame delay measurement code here
// Example: Use Choreographer, GPU Info, or Android Studio Profiler
// Reference: https://developer.android.com/topic/performance/vitals/render
Log.d("FrameDelay", "Hello World - Add your measurement code here!")
}
}
Thresholds
How to Measure
// iOS Frame Delay Measurement - Hello World Placeholder
// TODO: Replace with actual implementation for your app
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// TODO: Add your frame delay measurement code here
// Example: Use CADisplayLink, Xcode Instruments, or Core Animation profiling
// Reference: https://developer.apple.com/documentation/xcode/understanding-hangs-in-your-app#Understand-hangs
print("Hello World - Add your measurement code here!")
}
}
Thresholds
Calculating Mobile Vitals Score
Individual Metrics
The good
, meh
, bad
measurement for each individual metric is calculated based on the observed behaviour of Sentry's corpus of mobile telemetry, along with other telemetry that has been provided by the community.
A score in the 8th percentile or higher, represents good
, a score of 25th percentile or higher meh
, and a score below the 25th percentile is bad
.
Scores are further broken out by Android and iOS, as there's significant variation between the two device types.
Overall Score
Similar to lighthouse performance-scoring, the overall score provides a score between 1 and 100 for Mobile Vitals, based on a log-normal distribution of each weighted score.
Each individual score is weighted as follows, join the discussion in CONTRIBUTING if you'd like to help shape the weighting that's applied (this is a first pass, based on our best guesses).