-
Notifications
You must be signed in to change notification settings - Fork 625
Fireperf: encapsulate FrameMetricsAggregator
in a new object called FrameMetricsRecorder
#3665
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
Conversation
Coverage Report 1Affected Products
Test Logs
Notes |
Size Report 1Affected Products
Test Logs
Notes |
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/metrics/FrameMetricsCalculator.java
Outdated
Show resolved
Hide resolved
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.
Before reviewing the changes themselves, can you explain why we want to have this?
Could you mark this PR to ready for review and I can take another look? |
Done. I changed base branch to a new feature branch |
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/test/java/com/google/firebase/perf/application/FrameMetricsRecorderTest.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/test/java/com/google/firebase/perf/application/FrameMetricsRecorderTest.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/test/java/com/google/firebase/perf/application/FrameMetricsRecorderTest.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/test/java/com/google/firebase/perf/application/FrameMetricsRecorderTest.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/test/java/com/google/firebase/perf/application/FrameMetricsRecorderTest.java
Show resolved
Hide resolved
/retest |
…ts follow unit test practices
/retest |
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Show resolved
Hide resolved
|
||
/** Starts recording FrameMetrics for the activity window. */ | ||
public void start() { | ||
if (isRecording) { |
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.
Can you also expose an API isRecordingFrameMetricsForActivity(Activity activity)
? This would ensure that the caller knows the current state before starting to track an 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.
I am not sure what value that API would add because I don't see us using it. We are just going to call start()
in onActivityStart
and stop()
in onActivityStop
, if it fails then we are not doing symmetrical calls and we are calling start()
somewhere else, which is wrong and it should output warning.
In addition I don't think we should expose internal state, that's opening the blackbox. if start()
stop()
are called wrong and causes internal state to be problematic, that's a problem that should be contained in the blackbox, all the outside has to know is that "I used this black box in the wrong way".
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.
+1 to Leo
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'm mixed on this. I have seen usecases where having such an API would be very useful. But in the interest of self-containment, I'm fine to move ahead here.
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/main/java/com/google/firebase/perf/metrics/FrameMetricsCalculator.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/test/java/com/google/firebase/perf/application/FrameMetricsRecorderTest.java
Outdated
Show resolved
Hide resolved
firebase-perf/src/test/java/com/google/firebase/perf/application/FrameMetricsRecorderTest.java
Show resolved
Hide resolved
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 for working on this and spending the time to make the changes!
firebase-perf/src/main/java/com/google/firebase/perf/application/FrameMetricsRecorder.java
Show resolved
Hide resolved
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 Leo for your hard work! Great work!
b/229123892
TLDR
Add a new class called
FrameMetricsRecorder
that is essentially an encapsulation ofFrameMetricsAggregator
. Every activity will have an instance ofFrameMetricsRecorder
.Timeline Graph to Understand The Relationship between Activity, Fragments, and FrameMetricsAggregator
This an example of what is happening on a timeline. Fragment can be ANY UI object that is meaningful. e.g.) a listview that caused performance problems before, want to have screen traces for it to catch when such happens again in the future.

Background
Following the stopping screen trace in onActivityPostPaused change and realizing that is unviable due to onActivityPostPause being only available in API 29+, a new design is needed for screen rendering tracing.
Why encapsulate FMA
There's 2 main reasons:
AppStateMonitor
, a class with too much responsibilityClasses like
AppStateMonitor
are very heavy with many responsibilities: manageFrameMetricsAggregator
, instrument, create, and build proto for screen trace and _fs/_bs traces, etc. All which are on top of its responsibility of registering itself for activity lifecycle callbacks, which is already a lot of boilerplate to read through. This makes it hard to test and debug.Massive “god classes” like
AppStateMonitor
are also error prone and any small change could break it.FrameMetricsAggregator
is an example of an intricate class that requires special knowledge to handle, and that is only one responsibility in a very bloated class AppStateMonitor. To debug the Activity screen trace bug, you need to read through other code that is unrelated to screen traces, which is adding a lot more mental load to figure out how everything interacts with each other.Responsibility of
FrameMetricsRecorder
A manager for
FrameMetricsAggregator
, includes FMA instantiation, start activity recording, stop activity recording, calculating differences inFrameMetricsAggregator
’s data for a sub-trace (e.g. Fragment trace). Basically it only has a single responsibility: abstract awayFrameMetricsAggregator
and anything related to it.Design Rationale
Structurally enforces only 1 activity is being passed into each
FrameMetricsAggregator
.Activity
in the constructor, and creates a single privateFrameMetricsAggregator
.Structurally prevent misuse of
FrameMetricsAggregator
FrameMetricsAggregator
, guards can be put in place to prevent misuse.e.g.) in start(), can check if FMA is already recording, if it is, don’t allow it.
Simplify code and encapsulate responsibility
PerfFrameMetrics
, FMA is completely contained and encapsulated within this class.AppStateMonitor
doesn't manageFrameMetricsAggregator
, it simply callsstart()
andstop()
.Structure