Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Add traces to Android embedding #29230

Merged
merged 9 commits into from
Oct 29, 2021
Merged

Conversation

jiahaog
Copy link
Member

@jiahaog jiahaog commented Oct 18, 2021

flutter/flutter#91280, b/201473640

These traces will show up in systrace / Perfetto, making performance work easier.

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide and the C++, Objective-C, Java style guides.
  • I listed at least one issue that this PR fixes in the description above.
  • I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test-exempt. See testing the engine for instructions on
    writing and running engine tests.
  • I updated/added relevant documentation (doc comments with ///).
  • I signed the CLA.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@jiahaog
Copy link
Member Author

jiahaog commented Oct 18, 2021

Is flutter/android/embedding_bundle or something supposed to be updated here to fix the build failures? Would appreciate some help here :)

@@ -9,6 +9,7 @@
import android.content.res.AssetManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.tracing.Trace;
Copy link
Contributor

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?

Copy link

Choose a reason for hiding this comment

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

+1

Copy link
Member

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.

Copy link
Member

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

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 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");
Copy link
Contributor

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.

Copy link

Choose a reason for hiding this comment

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

also nit: FlutterEngine#attachToJni

Copy link
Member Author

@jiahaog jiahaog Oct 19, 2021

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)

Copy link
Member Author

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");
Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto?

Copy link
Member Author

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(
Copy link
Contributor

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.

Copy link
Member Author

@jiahaog jiahaog Oct 21, 2021

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");
Copy link
Contributor

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.

Copy link
Member Author

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");
Copy link
Contributor

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?

Copy link
Member Author

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);
Copy link
Contributor

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.

Copy link
Member

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)?

Copy link
Member Author

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?

Copy link
Contributor

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");
Copy link
Contributor

Choose a reason for hiding this comment

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

Async section.

Copy link
Member Author

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"
Copy link
Contributor

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?

Copy link
Member Author

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",
Copy link
Member

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

Copy link
Member Author

@jiahaog jiahaog Oct 21, 2021

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

Copy link
Member Author

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);
Copy link
Member

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)?

@blasten
Copy link

blasten commented Oct 18, 2021

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

@jiahaog
Copy link
Member Author

jiahaog commented Oct 19, 2021

If not, we may be able to use R8 to fully remove this dependency from builds that don't need it

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

@jiahaog
Copy link
Member Author

jiahaog commented Oct 19, 2021

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 android.os.Trace that I'd expect we'd need to write ourselves if we use android.os.Trace directly.

@blasten
Copy link

blasten commented Oct 19, 2021

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

R8 is able to tree shake code that isn't reachable too, so if (EVALUATES_TO_FALSE) { callLibrary() } should be able to delete callLibrary if this isn't necessary for all users, but no need to add it if the impact is tiny.

@jiahaog
Copy link
Member Author

jiahaog commented Oct 19, 2021

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 androidx.tracing.Trace vs rolling our own wrappers around android.os.Trace to deal with versioning.

$ ls -l
total 20904
-rw-r--r--  1 jiahaog  primarygroup  5348729 Oct 19 16:47 base.apk
-rw-r--r--  1 jiahaog  primarygroup  5349767 Oct 19 16:37 expt.apk

@jiahaog
Copy link
Member Author

jiahaog commented Oct 21, 2021

Ran an A/B test internally and didn't see any significant changes to the benchmarks beyond the usual noise.

engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 30, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 30, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 30, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 30, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 31, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 31, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 31, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 31, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 31, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 31, 2021
jiahaog added a commit to jiahaog/flutter-engine that referenced this pull request Nov 1, 2021
This reverts commit 8d7d4e7.

Manually resolved conflict in tools/androidx/files.json
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 1, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 1, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 1, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cla: yes needs tests platform-android waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants