-
-
Notifications
You must be signed in to change notification settings - Fork 338
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
Fix: Implement fallback system to screens that aren't reporting on the native layer the time to display. #4042
Conversation
Android (legacy) Performance metrics 🚀
|
Revision | Plain | With Sentry | Diff |
---|---|---|---|
5ba6409 | 516.43 ms | 521.07 ms | 4.63 ms |
ca043af | 422.28 ms | 408.35 ms | -13.93 ms |
993f0a4 | 486.06 ms | 505.04 ms | 18.98 ms |
5285e19 | 467.43 ms | 471.20 ms | 3.77 ms |
3503ebe | 484.89 ms | 465.06 ms | -19.83 ms |
33f0cfb | 366.32 ms | 409.22 ms | 42.90 ms |
6e1c646 | 457.75 ms | 439.92 ms | -17.83 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
5ba6409 | 17.73 MiB | 20.07 MiB | 2.33 MiB |
ca043af | 17.73 MiB | 20.11 MiB | 2.38 MiB |
993f0a4 | 17.73 MiB | 20.06 MiB | 2.33 MiB |
5285e19 | 17.73 MiB | 20.07 MiB | 2.33 MiB |
3503ebe | 17.73 MiB | 20.11 MiB | 2.38 MiB |
33f0cfb | 17.73 MiB | 20.07 MiB | 2.33 MiB |
6e1c646 | 17.73 MiB | 20.11 MiB | 2.38 MiB |
Android (new) Performance metrics 🚀
|
Revision | Plain | With Sentry | Diff |
---|---|---|---|
993f0a4+dirty | 432.25 ms | 491.56 ms | 59.31 ms |
5285e19+dirty | 418.18 ms | 460.47 ms | 42.29 ms |
ca043af+dirty | 411.53 ms | 441.56 ms | 30.03 ms |
33f0cfb+dirty | 431.30 ms | 492.47 ms | 61.17 ms |
6e1c646+dirty | 417.20 ms | 482.69 ms | 65.50 ms |
5ba6409+dirty | 436.37 ms | 445.90 ms | 9.53 ms |
3503ebe+dirty | 384.49 ms | 433.86 ms | 49.37 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
993f0a4+dirty | 7.15 MiB | 8.34 MiB | 1.19 MiB |
5285e19+dirty | 7.15 MiB | 8.34 MiB | 1.19 MiB |
ca043af+dirty | 7.15 MiB | 8.39 MiB | 1.24 MiB |
33f0cfb+dirty | 7.15 MiB | 8.34 MiB | 1.19 MiB |
6e1c646+dirty | 7.15 MiB | 8.39 MiB | 1.24 MiB |
5ba6409+dirty | 7.15 MiB | 8.34 MiB | 1.19 MiB |
3503ebe+dirty | 7.15 MiB | 8.39 MiB | 1.24 MiB |
iOS (legacy) Performance metrics 🚀
|
Revision | Plain | With Sentry | Diff |
---|---|---|---|
33f0cfb+dirty | 1220.29 ms | 1214.19 ms | -6.10 ms |
993f0a4+dirty | 1238.52 ms | 1241.51 ms | 2.99 ms |
5ba6409+dirty | 1209.31 ms | 1207.46 ms | -1.85 ms |
ca043af+dirty | 1229.50 ms | 1231.31 ms | 1.81 ms |
6e1c646+dirty | 1221.02 ms | 1234.47 ms | 13.45 ms |
5285e19+dirty | 1234.54 ms | 1235.31 ms | 0.76 ms |
3503ebe+dirty | 1222.44 ms | 1228.13 ms | 5.69 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
33f0cfb+dirty | 2.36 MiB | 3.08 MiB | 735.59 KiB |
993f0a4+dirty | 2.36 MiB | 3.08 MiB | 732.19 KiB |
5ba6409+dirty | 2.36 MiB | 3.08 MiB | 735.56 KiB |
ca043af+dirty | 2.36 MiB | 3.14 MiB | 794.23 KiB |
6e1c646+dirty | 2.36 MiB | 3.14 MiB | 794.20 KiB |
5285e19+dirty | 2.36 MiB | 3.08 MiB | 735.56 KiB |
3503ebe+dirty | 2.36 MiB | 3.14 MiB | 794.22 KiB |
iOS (new) Performance metrics 🚀
|
Revision | Plain | With Sentry | Diff |
---|---|---|---|
33f0cfb+dirty | 1247.61 ms | 1241.02 ms | -6.59 ms |
993f0a4+dirty | 1241.51 ms | 1235.85 ms | -5.66 ms |
5ba6409+dirty | 1231.40 ms | 1236.81 ms | 5.42 ms |
ca043af+dirty | 1230.57 ms | 1226.55 ms | -4.02 ms |
6e1c646+dirty | 1232.62 ms | 1239.96 ms | 7.34 ms |
5285e19+dirty | 1228.69 ms | 1218.22 ms | -10.47 ms |
3503ebe+dirty | 1219.50 ms | 1232.69 ms | 13.19 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
33f0cfb+dirty | 2.92 MiB | 3.64 MiB | 741.43 KiB |
993f0a4+dirty | 2.92 MiB | 3.64 MiB | 738.79 KiB |
5ba6409+dirty | 2.92 MiB | 3.64 MiB | 741.50 KiB |
ca043af+dirty | 2.92 MiB | 3.69 MiB | 794.99 KiB |
6e1c646+dirty | 2.92 MiB | 3.69 MiB | 795.00 KiB |
5285e19+dirty | 2.92 MiB | 3.64 MiB | 741.52 KiB |
3503ebe+dirty | 2.92 MiB | 3.69 MiB | 795.00 KiB |
Hi @lucas-zimerman, I think waiting for the next drawn frame is a good fallback. But there is one party breaker hidden in the RN implementation. Compared to browsers implementation, in RN requestAnimationFrame -> CreateTimer -> Timer is hook to DisplayLink of JS Thread DisplayLink uses current thread -> JS Thread This means the callback runs after the React Native Node Tree is assembled and passed to native. So unless the JS loop is doing some heavy task, it will generally be executed before the render. We can fix that by implementing our own
The native implementation would the same method to hook into the render loop as RNSentryOnDrawReporterView but instead of component it would be native method of RNSentry. I think we can still use the JS It should work well with the current draft, replacing Let me know what you think, if my though process make sense, or I've missed something. |
The Android integration is done, we will now finish the iOS integration |
…ile, add js implementation as fallback
* Emitter suggestion * fix tests --------- Co-authored-by: Krystof Woldrich <[email protected]>
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
android/src/main/java/io/sentry/react/RNSentryTimeToDisplay.java
Outdated
Show resolved
Hide resolved
Thank you @lucas-zimerman, it's looking good. I've noticed one last thing with the choreographer. See #4042 (comment) |
I've changed the target to But we should include this also in version 6. First we release it as beta on v5 and then also as a hotfix on |
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! @lucas-zimerman
Large improvement for TTD.
Can you port this also to v6 (main)? |
Sure thing, I will port it to V6 |
📢 Type of change
📜 Description
Context: the current native implementation doesn't always emit the required event in order to track the required time to display to be set on the time to display span.
To fix that, I introduced an additional fallback emitter, in short, it reuses the same flow by emitting the original event when the fallback emitter received the notification that the page was rendered and the original emitter didn't emit any event on the following 3 seconds.
With those changes, we have the following benefits:
💡 Motivation and Context
Close #3934, #3809
💚 How did you test it?
The playground tab on our sample is a good case for testing, since it doesn't use navigation stack on it, the events on this condition are limited, not generating and required event by us in order to track the time to display.
I used it and other tabs to compare the difference between the original implementation and also
requestAnimationFrame
, and the time difference between each other was quite low:1St Tab
JS: requestAnimationFrame, "newFrameTimestampInSeconds" is 1724293664.8300002
Original: InitAsync Event received {"newFrameTimestampInSeconds":1724293664.8179998}
2Nd Tab
JS: requestAnimationFrame, "newFrameTimestampInSeconds" is 1724293761.688
Original: InitAsync Event received {"newFrameTimestampInSeconds":1724293761.689}
3Rd Tab
JS: requestAnimationFrame, "newFrameTimestampInSeconds" is 1724293824.887
Original: Android didn't emit an event for this page so it wasn't measured
Before this change on the playground screen:
https://sentry-sdks.sentry.io/performance/trace/10bd4bf28052404592f408f3cf58175a/?dataset=transactions&field=title&field=event.type&field=project&field=user.display&field=timestamp&field=replayId&fov=0%2C15046.88916015625&id=21705&name=&node=trace-root&project=5428561&query=&queryDataset=transaction-like&sort=-timestamp&source=discover&statsPeriod=1h×tamp=1724358725&topEvents=5&yAxis=count%28%29
After this change on the playground screen:
https://sentry-sdks.sentry.io/performance/trace/8cb478b4370e444fa4a7b9be778d51ab/?dataset=transactions&field=title&field=event.type&field=project&field=user.display&field=timestamp&field=replayId&fov=0%2C235&id=21705&name=&node=txn-b5a8ba18aa254fe79743133baf9071b2&project=5428561&query=&queryDataset=transaction-like&sort=-timestamp&source=discover&statsPeriod=1h×tamp=1724359145&topEvents=5&yAxis=count%28%29
📝 Checklist
sendDefaultPII
is enabled🔮 Next steps