Skip to content
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

Reset frames tracker on activity started #2269

Closed
wants to merge 3 commits into from

Conversation

adinauer
Copy link
Member

📜 Description

Fixes the wrong reporting of frames by resetting the count via onActivityStarted.

💡 Motivation and Context

Fixes #2264

💚 How did you test it?

Played around with our sample app. Looks like it's working. Only saw some occurrences where the reset was logged before extracting the number of frames but that was on a total frame count of 0 so instantly done. Might have just been the logger printing the messages in wrong order. On total frame counts > 0 i never saw a reversed order.

📝 Checklist

  • I reviewed the submitted code
  • I added tests to verify the changes
  • I updated the docs if needed
  • No breaking changes

🔮 Next steps

Copy link
Member

@bruno-garcia bruno-garcia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RSLGTM

@@ -54,6 +54,7 @@ public synchronized void addActivity(final @NotNull Activity activity) {
if (!isFrameMetricsAggregatorAvailable()) {
return;
}
frameMetricsAggregator.reset();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible we have one activity alive with a transaction happening at the time a new one kicks off? Where the reset breaks reporting the values for the first activity?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know you can only have one activity at a time. So for transactions that use ActivityFramesTracker there should not be more than one. But maybe @romtsn or @marandaneto know better.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I think this could be a problem if users disable auto-finish of the activity transactions and finish them manually in onStop. Because when you launch a second Activity, the lifecycle will be like this:

ActivityA->onPause
ActivityB->onCreate
ActivityB->onStart
ActivityB->onResume
ActivityA->onStop

so in this case when the ActivityA transaction gets finished in onStop it will have no metrics (or maybe even the wrong metrics from the ActivityB)

Needs to be tested though, just my assumption based on https://developer.android.com/guide/components/activities/activity-lifecycle#coordinating-activities

Copy link
Member Author

@adinauer adinauer Oct 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm need to think some more here. Our other solution was to do the reset after retrieving the counts.

Then this would also cause issues:

ActivityA->onPause
ActivityB->onCreate
ActivityB->onStart [frames should start counting here]
ActivityB->onResume
ActivityA->onStop [reset happens; losing counts from ActivityB as well]

So counts wouldn't be accurate.


Yet another approach was to take snapshots

ActivityA->onPause
ActivityB->onCreate [start snapshot for ActivityB happens here]
ActivityB->onStart
ActivityB->onResume
ActivityA->onStop [stop snapshot for ActivityA happens here]

When can we call reset here and not lose any counts?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this needs to be a multi-step collection process so we get to call reset somewhere?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some quick testing:

It stores counts in a SparseIntArray thus only adding an entry for each ms duration value that any frame took (including a count of many frames fell in that time range). As time goes by this means we'll probably have every possible ms length value in the array. For very long transactions (e.g. if a user stayed on a screen for a very long time) and long usage periods on the app this might actually cause problems as we'll have more and more values in the array. So this alone doesn't feel like the right approach to me. Ideally I'd like to get a reset in there somewhere. That's why I suggested we break the tracking apart. Question is if this is worth the effort to invest here if we should rather go with a different appraoch based on Choreographer which we could then also use to track UI events etc.

Copy link
Member

@romtsn romtsn Oct 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah feels like custom framecallback approach is the most viable here. We could also persist intermediate counts for ActivityB, so they don't get lost after calling reset, and then sum them up with the new counts after the reset, but if the Choreographer approach is a silver bullet for them all, I'd go for it probably

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After having a call about this we decided to move forward with calculating the delta value and keep using a single frameMetricsAggregator. If that causes problems we can either use one frameMetricsAggregator per transaction or Activity or investigate e.g. jank stats.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that calculating the delta with a single frameMetricsAggregator should be fine. The distribution of frames should be around 16 ms. I don't expect the SparseIntArray to get too big. Even if we have 1000 different frame durations, which is highly unlikely, we only need 1000 * 32 * 2 bits ~ 8 KiB. We never called reset until now, and it seemed not to cause a memory issue.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@philipphofmann yeah the case I was worried about was more the one where it tracks until onActivityStopped which might me significantly longer.

@github-actions
Copy link
Contributor

github-actions bot commented Sep 30, 2022

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 355.58 ms 407.24 ms 51.66 ms
Size 1.73 MiB 2.29 MiB 578.74 KiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
2f079a1 296.91 ms 337.43 ms 40.51 ms
3d89dea 345.59 ms 364.06 ms 18.47 ms
3d89dea 322.38 ms 350.82 ms 28.45 ms
1e4690d 354.69 ms 387.88 ms 33.19 ms
c5ccd8a 329.98 ms 365.52 ms 35.54 ms

App size

Revision Plain With Sentry Diff
2f079a1 1.74 MiB 2.33 MiB 605.56 KiB
3d89dea 1.74 MiB 2.33 MiB 604.92 KiB
3d89dea 1.74 MiB 2.33 MiB 604.92 KiB
1e4690d 1.74 MiB 2.33 MiB 604.92 KiB
c5ccd8a 1.74 MiB 2.33 MiB 607.44 KiB

Previous results on branch: fix/reset-frame-counter-on-activity-started

Startup times

Revision Plain With Sentry Diff
2d5b147 308.74 ms 344.52 ms 35.78 ms

App size

Revision Plain With Sentry Diff
2d5b147 1.73 MiB 2.29 MiB 578.74 KiB

@codecov-commenter
Copy link

Codecov Report

Base: 80.07% // Head: 80.07% // No change to project coverage 👍

Coverage data is based on head (5348768) compared to base (7300956).
Patch has no changes to coverable lines.

Additional details and impacted files
@@            Coverage Diff            @@
##               main    #2269   +/-   ##
=========================================
  Coverage     80.07%   80.07%           
  Complexity     3415     3415           
=========================================
  Files           241      241           
  Lines         12636    12636           
  Branches       1697     1697           
=========================================
  Hits          10118    10118           
  Misses         1876     1876           
  Partials        642      642           

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.
📢 Do you have feedback about the report comment? Let us know in this issue.

@marandaneto
Copy link
Contributor

ActivityFramesTracker is used by Hybrid SDKs, if all the changes are considered breaking changes (the public API), we'd need to fix the Hybrid SDKs as well, let me know if that's the case.

@adinauer
Copy link
Member Author

adinauer commented Oct 3, 2022

Closed in favor of #2271

@adinauer adinauer closed this Oct 3, 2022
@romtsn romtsn deleted the fix/reset-frame-counter-on-activity-started branch July 19, 2023 09:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Slow and Frozen frames are reported wrongly for Activity transactions
6 participants