-
Notifications
You must be signed in to change notification settings - Fork 6k
Add traces to Android embedding #29230
Conversation
78abb17
to
a3b6a41
Compare
Is |
@@ -9,6 +9,7 @@ | |||
import android.content.res.AssetManager; | |||
import androidx.annotation.NonNull; | |||
import androidx.annotation.Nullable; | |||
import androidx.tracing.Trace; |
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.
Does this require a new jar from AndroidX?
If so, can we just use android.os.Tracing
?
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
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.
The AndroidX wrapper abstracts the differences in support for the tracing APIs across various versions of Android.
It might be worthwhile to regenerate the android_embedding_dependencies package. Many of the libraries in there can probably be removed now that Robolectric dependencies are being obtained dynamically by the Gradle-based test runner.
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.
PR for the android_embedding_dependencies update: #29233
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.
As Jason mentioned, it's a small abstraction over nuances like SDK versions. We're probably going to need to roll our own implementations anyway if we don't use it, and it seems like androidx APIs are pretty much aligned with the rest of the Android ecosystem. Lmk if there are strong objections to this though.
@@ -356,11 +357,18 @@ public FlutterEngine( | |||
} | |||
|
|||
private void attachToJni() { | |||
Trace.beginSection("FlutterEngine attachToJni"); |
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 think this one needs to be an async section.
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.
also nit: FlutterEngine#attachToJni
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.
@dnfield can you point me to where this async section should end? (Also for destroy
)
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.
Removed, since it isn't useful for us at this point anyway
@@ -411,20 +419,26 @@ private boolean isAttachedToJni() { | |||
* <p>This {@code FlutterEngine} instance should be discarded after invoking this method. | |||
*/ | |||
public void destroy() { | |||
Trace.beginSection("FlutterEngine destroy"); |
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.
Ditto?
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.
Removed, since it isn't useful for us at this point anyway
@@ -83,7 +84,8 @@ public DartExecutor(@NonNull FlutterJNI flutterJNI, @NonNull AssetManager assetM | |||
public void onAttachedToJNI() { | |||
Log.v( |
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.
nit: consider removing these in favor of trace statements.
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.
Did not do this since the above onAttachedToJNI was also removed and we don't really need it
@@ -250,7 +263,12 @@ public void setIsolateServiceIdListener(@Nullable IsolateServiceIdListener liste | |||
*/ | |||
public void notifyLowMemoryWarning() { | |||
if (flutterJNI.isAttached()) { | |||
flutterJNI.notifyLowMemoryWarning(); | |||
Trace.beginSection("DartExecutor notifyLowMemoryWarning"); |
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.
There's already some tracing for this in the engine and in Dart. I don't think we need it here - we'd effectively just be tracing the JNI overhead, which is small.
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.
Removed, thanks
@@ -147,15 +155,20 @@ public void executeDartCallback(@NonNull DartCallback dartCallback) { | |||
return; | |||
} | |||
|
|||
Trace.beginSection("DartExecutor executeDartCallback"); |
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 suspect this would want to be an async one, but I also think we have a bunch of tracing around this already in the C++ side. Is this adding much value?
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.
This one might be still useful for diagnostics since different apps can call this at different points (depending on whether they use FlutterActivity / roll their own)
@@ -60,15 +61,21 @@ public void send( | |||
@NonNull String channel, | |||
@Nullable ByteBuffer message, | |||
@Nullable BinaryMessenger.BinaryReply callback) { | |||
Trace.beginSection("DartMessenger send on " + channel); |
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 think this might be better to do on the Dart side in the Flutter framework. It also might want to be async to see if we could capture the reply as well.
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 for the spirit of these 2, but adding this here might get spammy and possibly affect runtime performance. Can we try this locally on GPay and see how much traffic this adds (and possibly run an ab test)?
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.
Yes. async traces will be helpful here as well. This one seems to be useful though - it tells us when the main thread is blocked by a plugin callback. At the same time, having both this one and also traces on the Dart side allows us to observe how long the platform message is queued before it is able to make the thread jump?
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.
That makes sense to me.
@@ -202,6 +215,8 @@ public void ensureInitializationComplete( | |||
throw new IllegalStateException( | |||
"ensureInitializationComplete must be called after startInitialization"); | |||
} | |||
Trace.beginSection("FlutterLoader ensureInitializationComplete"); |
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.
Async section.
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.
Correct me if I'm wrong, but this piece doesn't look like it's async and the method blocks until it's done
@@ -42,6 +42,7 @@ android { | |||
dependencies { | |||
embedding "androidx.annotation:annotation:1.1.0" | |||
embedding "androidx.fragment:fragment:1.1.0" | |||
embedding "androidx.tracing:tracing:1.0.0" |
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.
Let's avoid this if we can - what does it add over android.os.trace
?
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.
Discussed above :)
@@ -49,5 +49,13 @@ | |||
"androidx.annotation.UiThread", | |||
"androidx.annotation.VisibleForTesting" | |||
] | |||
}, | |||
{ | |||
"url": "https://maven.google.com/androidx/tracing/tracing/1.0.0/tracing-1.0.0.aar", |
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 think it's ok but for posterity, this is adding 4kB to all Flutter users
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.
Commented below a bit more - if you're referring to the .aar file, it is a 4KB build dependency, but much less when built into an APK
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.
Is the change to this file necessary though? I removed it but it seemed to build correctly
@@ -60,15 +61,21 @@ public void send( | |||
@NonNull String channel, | |||
@Nullable ByteBuffer message, | |||
@Nullable BinaryMessenger.BinaryReply callback) { | |||
Trace.beginSection("DartMessenger send on " + channel); |
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 for the spirit of these 2, but adding this here might get spammy and possibly affect runtime performance. Can we try this locally on GPay and see how much traffic this adds (and possibly run an ab test)?
Since this is adding 4KB, are all users going to use this feature? If not, we may be able to use R8 to fully remove this dependency from builds that don't need it. https://developer.android.com/studio/build/shrink-code#optimization |
The tracing calls have to be built into the app since this is only configurable at runtime, but some methods we don't call should be tree shaken |
https://maven.google.com/androidx/tracing/tracing/1.0.0/tracing-1.0.0.aar will add 4KB to Flutter users at build time, but much less of that 4KB would probably be built into the APK (will do some builds and update). As seen from the source, it is really a thin wrapper around |
R8 is able to tree shake code that isn't reachable too, so |
It's a ~1KB difference in the APK size, including all the changes from this PR. I think this should be small enough and it wouldn't make a difference whether we use
|
Ran an A/B test internally and didn't see any significant changes to the benchmarks beyond the usual noise. |
This reverts commit 8d7d4e7. Manually resolved conflict in tools/androidx/files.json
flutter/flutter#91280, b/201473640
These traces will show up in systrace / Perfetto, making performance work easier.
Pre-launch Checklist
writing and running engine tests.
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.