-
-
Notifications
You must be signed in to change notification settings - Fork 444
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 slow and frozen frames tracking #2271
Conversation
Performance metrics 🚀
|
Revision | Plain | With Sentry | Diff |
---|---|---|---|
5f9ea6f | 304.71 ms | 345.49 ms | 40.78 ms |
001064a | 327.52 ms | 390.29 ms | 62.77 ms |
926b4a3 | 307.96 ms | 347.68 ms | 39.72 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
5f9ea6f | 1.74 MiB | 2.33 MiB | 605.44 KiB |
001064a | 1.74 MiB | 2.33 MiB | 605.44 KiB |
926b4a3 | 1.74 MiB | 2.33 MiB | 605.44 KiB |
@@ -1,5 +1,9 @@ | |||
# Changelog | |||
|
|||
## Unreleased | |||
|
|||
- Fix slow and frozen frames tracking ([#2271](https://github.com/getsentry/sentry-java/pull/2271)) |
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.
@marandaneto since no public API changes were necessary I assume this fix doesn't require any further action on hybrid SDKs.
I just did a review for this PR and looked at the If I'm not mistaken, we can't have multiple auto generated activity transactions running in parallel, because call Lines 152 to 156 in 7300956
So either we keep the code in |
The problem is if the transaction still has unfinished children, then calling |
Ah, I missed that one, thanks for pointing that out. |
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.
One edge case maybe to fix. Almost LGTM. Thanks for fixing this, @adinauer 👏 .
I added plenty of nitpicks; you can ignore them if you want. Just minor things to improve the readability of the code a bit. Some of them could also be personal preference.
sentry-android-core/src/test/java/io/sentry/android/core/ActivityFramesTrackerTest.kt
Outdated
Show resolved
Hide resolved
sentry-android-core/src/test/java/io/sentry/android/core/ActivityFramesTrackerTest.kt
Outdated
Show resolved
Hide resolved
it.put(1, 110) | ||
it.put(20, 6) | ||
it.put(705, 7) |
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.
m
: Testing with boundary values of the equivalence classes [0-16] [17-700] [701 - infinity]
makes the tests a bit better. This helps to detect off by 1 errors.
it.put(1, 110) | |
it.put(20, 6) | |
it.put(705, 7) | |
it.put(16, 110) | |
it.put(17, 3) // Splitted up 20 | |
it.put(700, 3) | |
it.put(701, 7) |
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.
Just used the values that were there in old tests; can update
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.
Up to you.
sentry-android-core/src/test/java/io/sentry/android/core/ActivityFramesTrackerTest.kt
Outdated
Show resolved
Hide resolved
val arrayAll = SparseIntArray() | ||
arrayAll.put(1, 100) | ||
arrayAll.put(20, 5) | ||
arrayAll.put(705, 6) |
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.
l
:
val arrayAll = SparseIntArray() | |
arrayAll.put(1, 100) | |
arrayAll.put(20, 5) | |
arrayAll.put(705, 6) | |
val arrayAll = SparseIntArray().apply { | |
put(1, 100) | |
put(20, 5) | |
put(705, 6) | |
} |
sentry-android-core/src/test/java/io/sentry/android/core/ActivityFramesTrackerTest.kt
Outdated
Show resolved
Hide resolved
@@ -27,6 +28,8 @@ public final class ActivityFramesTracker { | |||
|
|||
private final @NotNull Map<SentryId, Map<String, @NotNull MeasurementValue>> | |||
activityMeasurements = new ConcurrentHashMap<>(); | |||
private final @NotNull Map<Activity, FrameCounts> frameCountAtStartSnapshots = |
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.
I like the name 👏
final FrameCounts frameCountsAtStart = | ||
frameCountsAtStartFromMap == null ? new FrameCounts(0, 0, 0) : frameCountsAtStartFromMap; |
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.
m
: When do we run into this edge case that the frameCountsAtStartFromMap
is null
? We already check that the activity is not null
here
Lines 169 to 172 in f6b0dc7
@Nullable Activity unwrappedActivity = weakActivity.get(); | |
if (unwrappedActivity != null) { | |
activityFramesTracker.setMetrics( | |
unwrappedActivity, finishingTransaction.getEventId()); |
The parameter is also annotated
@NotNull
. If this happens, something is wrong and I think we should better not count the frames at all and return null
here. If we use FrameCounts(0, 0, 0)
, I think we risk calculating incorrect frame counts.
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.
My idea here was that we might not be able to determine frame counts if the FrameMetricsAggregator
was freshly created as getMetrics()
on it is marked with @Nullable
. Since I changed some code around it shouldn't be necessary as we have a FrameCounts(0, 0, 0)
. Gonna change it so it doesn't calculate a difference if it can't find a start snapshot.
} | ||
} | ||
|
||
private @Nullable FrameCounts diffFrameCountsAtEnd(final @NotNull Activity activity) { |
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.
l
: I would move this method below setMetrics
, because it is the only function calling this method. Now when I read setMetrics
I have to jump all the way up to here to find the method. Keeping functions calling each other close to each other in the code improves readability, IMO.
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.
Thanks, forgot to reorder them
sentry-android-core/src/main/java/io/sentry/android/core/ActivityFramesTracker.java
Outdated
Show resolved
Hide resolved
…ityFramesTracker.java Co-authored-by: Philipp Hofmann <philipp.hofmann@sentry.io>
…ityFramesTrackerTest.kt Co-authored-by: Philipp Hofmann <philipp.hofmann@sentry.io>
…ityFramesTrackerTest.kt Co-authored-by: Philipp Hofmann <philipp.hofmann@sentry.io>
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 @adinauer 👏
} | ||
|
||
private @Nullable FrameCounts diffFrameCountsAtEnd(final @NotNull Activity activity) { | ||
@Nullable final FrameCounts frameCountsAtStart = frameCountAtStartSnapshots.remove(activity); |
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.
Thanks 🙏
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## 6.4.x #2271 +/- ##
========================================
Coverage ? 80.62%
Complexity ? 3368
========================================
Files ? 240
Lines ? 12388
Branches ? 1646
========================================
Hits ? 9988
Misses ? 1791
Partials ? 609 Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
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.
LGTM 👍
📜 Description
Fixes the wrong reporting of frames by snapshotting slow and frozen frame values at the start and end, then calculating a delta.
💡 Motivation and Context
Fixes #2264
💚 How did you test it?
Sample App; Unit Tests
📝 Checklist
🔮 Next steps
Once merged, release
6.4.3
then merge6.4.x
intomain
.