Hidden costs of Firebase Performance and how to avoid them

Or “How using Performance SDK might harm your…performance”.

Andrii Chubko
ProAndroidDev

--

Original image by Rudy and Peter Skitterians from Pixabay

Almost every tool we bring into our Android codebase comes with a price. Firebase Performance is no exception, but its pitfalls may be even more peculiar and unexpected. In this article, we will explore the problems you might stumble upon as well as the ways to cope with them.

tl;dr

Pitfalls of using Firebase Performance Android SDK:

  • from 20–30 seconds up to several minutes of additional build time, use option 1 or option 2 to deal with this;
  • ~0.5mb increase in APK size and the corresponding increase in app install size;
  • ~4k-10k increase in the number of method references depending on your code shrinking setup and existing dependencies.

Interlude

So, using Firebase Performance makes you less performant? Wait, I sense a disturbance in the force, could it be…?

Well, I thought it was a trap but whatever. Let’s deal with it!

Hidden cost #1: APK size

Problem

Firebase Performance SDK (FP from now on) brings ~0.5mb increase to your APK download size. The impact on the app install size will vary from device to device but will be in the range of several megabytes.

Solution

We can’t fully address this issue, but using code shrinking tool will somewhat reduce the impact on installed app size.

Hidden cost #2: method count

Problem

The number of method references that FP will add varies from ~4k to ~10k. This number is affected by your code shrinking setup and your existing dependencies. For example, it will be much closer to the lower bound if you already use Firebase Core (aka Google Analytics).

Solution

Use ProGuard/R8/OtherShrinkingTool to alleviate this downside.

Hidden cost #3: build time

Problem

Ok, I know that previous items are not especially hidden as you should be aware that any new dependency you add will have these kinds of issues to some extent.

But not a lot of libraries that you use can lead to increasing your build time by minutes. And seeing how build time is already a huge sore spot for the Android community, this becomes a crucial issue.

The root of the problem stems from the transformClassesWithFirebasePerformancePluginFor* task which might take minutes to run.

Solution #1: Use `firebasePerformanceInstrumentationEnabled` property

This is the official way provided by the SDK itself to disable it during the build process.

What this does:

  • Reduces transformClassesWithFirebasePerformancePluginFor* task execution time to only ~5-10s.
  • Disables automatic traces and request monitoring but leaves custom traces enabled. You can control the latter with AndroidManifest <meta-data> tags and calls to FirebasePerformance.getInstance().setPerformanceCollectionEnabled(). More info in the docs.

How to do this:

I think it’s much easier to only enable the plugin in those rare cases when we need it (usually it will be only when we publish the app) rather than disable it at all the other times.

Note: Of course, with manual builds, you might forget to enable it. So, if you don’t have CI, it might be worth adding some other automatic scripting in Gradle or sticking to the opposite approach.

In general, though, we only need two steps:

  1. Add the following line to gradle.properties file:
firebasePerformanceInstrumentationEnabled=false

2. Use the following command in your CI config or manual builds:

gradlew assembleRelease -PfirebasePerformanceInstrumentationEnabled=true

Pros:

  • Only one property to set up.

Cons:

  • The plugin still adds extra~5–15s to the build time.

Solution #2: Use custom Gradle project property to avoid applying `firebase-perf` Gradle plugin

What this does:

  • transformClassesWithFirebasePerformancePluginFor* task is not executed at all. Also, we save some additional ~5–10s overhead that is present when using the first solution.
  • Same as the first method in regard to tracing.

How to do this:

This approach has the same points and warnings as the previous one, and also includes two steps:

  1. Modify your app module’s build.gradle file:
if (project.hasProperty('useFirebasePerf')) {
apply plugin: 'com.google.firebase.firebase-perf'
}

2. Use the following command in your CI config or manual builds:

gradlew assembleRelease -PuseFirebasePerf

Pros:

  • Completely eliminates time expenses associated with Firebase Performance Gradle plugin.

Cons:

  • Introduces conditional check for applying plugin in your Gradle script. Some might argue that it’s not an idiomatic approach.

* (Bonus option) Use custom Gradle project property to exclude `firebase-perf` SDK

If you don’t use custom traces or any other features from FP and only rely on automatic monitoring (that is, you don’t have any dependencies on the SDK in your code), then you can exclude this dependency for non-production builds.

How to do this:

All you need to do is update your app module’s build.gradle file:

  • If you chose Solution #1, then change your dependency like this:
  • If you chose Solution #2:

Advantages:

  • This might save you extra ~5–10s spent on configuring dependency and “ProGuarding” it.

Drawbacks:

  • Your production APK will be larger than debug one by ~0.5mb. This might disrupt your reports or predictions, so you need to be aware of it.
  • If you were close to surpassing 64K method count limit, you might suddenly step over it on production builds and find yourself in the MultiDex zone. And that means extra work to do and tests to run.

Conclusion

It turns out that things that are supposed to help you increase performance might have an adverse effect on it at the same time.

But now that you’re aware of the pitfalls of Firebase Performance SDK and their remedies, you can utilize it in the most effective way.

Final note: this article is born from this StackOverflow thread. I wasn’t fully satisfied with the answers that were already there, so I decided to contribute one myself.

--

--