perf(android): Move start-reason binder off main thread (JAVA-616) - #5866
Draft
runningcode wants to merge 2 commits into
Draft
perf(android): Move start-reason binder off main thread (JAVA-616)#5866runningcode wants to merge 2 commits into
runningcode wants to merge 2 commits into
Conversation
getHistoricalProcessStartReasons is an API 35+ binder round-trip to system_server that ran synchronously on the main thread at ContentProvider time, stalling the coldest part of app start. Run it on a background thread instead. The result is consumed best-effort: cold/warm falls back to the pre-API-35 heuristic and app.start.reason is null if the lookup has not resolved by the first activity.
📲 Install BuildsAndroid
|
Contributor
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 6b019b7 | 319.84 ms | 333.15 ms | 13.31 ms |
| c3ee041 | 310.64 ms | 361.90 ms | 51.26 ms |
| d501a7e | 348.06 ms | 431.42 ms | 83.36 ms |
| 3998a95 | 415.94 ms | 478.54 ms | 62.60 ms |
| ed33deb | 343.30 ms | 362.41 ms | 19.10 ms |
| 5b1a06b | 310.56 ms | 362.79 ms | 52.22 ms |
| 91bb874 | 310.68 ms | 359.24 ms | 48.56 ms |
| 0ee65e9 | 317.37 ms | 366.50 ms | 49.13 ms |
| 6edfca2 | 305.52 ms | 432.78 ms | 127.26 ms |
| 5e269de | 292.83 ms | 379.12 ms | 86.29 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 6b019b7 | 0 B | 0 B | 0 B |
| c3ee041 | 0 B | 0 B | 0 B |
| d501a7e | 0 B | 0 B | 0 B |
| 3998a95 | 1.58 MiB | 2.10 MiB | 532.96 KiB |
| ed33deb | 1.58 MiB | 2.13 MiB | 559.52 KiB |
| 5b1a06b | 0 B | 0 B | 0 B |
| 91bb874 | 1.58 MiB | 2.13 MiB | 559.07 KiB |
| 0ee65e9 | 0 B | 0 B | 0 B |
| 6edfca2 | 1.58 MiB | 2.13 MiB | 559.07 KiB |
| 5e269de | 0 B | 0 B | 0 B |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📜 Description
On API 35+,
AppStartMetrics.registerLifecycleCallbacksperformed anActivityManager.getHistoricalProcessStartReasons(1)binder call synchronously on the main thread. Under auto-init this runs atContentProvidertime (SentryPerformanceProvider.onAppLaunched), blocking the main thread on asystem_serverround-trip during the coldest part of app start.This moves the lookup onto a short-lived background daemon thread. The Sentry executor doesn't exist this early (ContentProvider time), so a plain thread is used.
cachedStartInfois nowvolatileand consumed best-effort:onActivityCreated: it prefers the resolvedApplicationStartInfoand falls back to the existing pre-API-35 heuristic if the lookup hasn't resolved yet.COLD.getAppStartReason()returnsnullif the lookup hasn't resolved by the time it is read.No public API change (
apiDumpclean).💡 Motivation and Context
JAVA-616. Fixes #5702.
The binder call stalled the main thread at the most latency-sensitive moment of startup. Measured on a Pixel 10 (API 36) across cold starts, the synchronous call cost ~0.5–2.2 ms of main-thread time (median ~0.7 ms, mean ~0.9 ms). Deferring it reclaims that time from the main thread.
💚 How did you test it?
AppStartMetricsTestApi35unit tests updated to inject a synchronous executor and driveonActivityCreated; all pass.cachedStartInfowas ready before the first activity in every observed cold start — even with the sample's artificial start-padding removed — so cold/warm andapp.start.reasonare preserved in practice.📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps