Firebase 性能插件导致构建时间变慢

Firebase Performance Plugin causing slow build time

在 Android Studio 中使用 Firebase Performance 时,gradle 任务 app:transformClassesWithFirebasePerformancePluginForDebug 比任何其他任务花费的时间都长得多,因此大大减慢了我的 gradle 构建时间.

Slow Build shown in Profiler

我们项目中的 Firebase 导致构建时间增加了 40%。为了加快调试构建,我们添加了一种可能性,可以使用 app/build.gradle 和根 build.gradle 文件中的构建参数来切换它 on/off:

应用程序:

if (!project.hasProperty("disable-performance-plugin"))  {
    apply plugin: 'com.google.firebase.firebase-perf' 
}

root/buildscript/dependencies:

if (!project.hasProperty("disable-performance-plugin")) {
    classpath('com.google.firebase:firebase-plugins:1.1.5') {
        exclude group: 'com.google.guava', module: 'guava-jdk5'
    }
}

当 运行 从命令行使用

./gradlew your-task  -Pdisable-performance-plugin

从 Android Studio 工作时,将标志添加到编译器选项:

只是为了提供另一个禁用 transformClassesWithFirebasePerformancePluginForDebug 的选项,这是我的食谱:

在主 build.gradle 文件夹中:

if (!project.gradle.startParameter.taskNames.any { taskName ->
     taskName.toLowerCase().contains('assemble') && taskName.toLowerCase().contains('debug') }) {
     classpath("com.google.firebase:firebase-plugins:$firebasePluginVersion") {
         exclude group: 'com.google.guava', module: 'guava-jdk5'
     }
}

在 build.gradle 应用程序文件中:

if (!project.gradle.startParameter.taskNames.any { taskName ->
    taskName.toLowerCase().contains('assemble') && taskName.toLowerCase().contains('debug') }) {
    apply plugin: 'com.google.firebase.firebase-perf'
}

我运行也遇到了这个问题。最初我们一直在使用 R. Zagórski 提供的答案的变体,但基于来自 Gradle 论坛的 similar thread 似乎有条件地将插件应用于项目并不是正确的方法开始:

Plugins can’t be applied to only “part of your project”. They are either applied or not.

有条件地应用插件似乎确实有效,但它不是官方支持的功能。在同一线程的下方,还有一点:

But the plugin should allow you to configure it at a finer grained level.

果然,Firebase 插件实际上公开了一个 属性,可让您打开或关闭检测(因此切换增加的构建时间)。但是,使用这个 属性 很棘手,因为你必须在构建过程中的正确时间应用它,但一旦你掌握了它,你就可以根据需要随意调整它。

以下代码片段是我们如何根据调试与非调试构建变体来调整检测。它是用 Kotlin 编写的,但我想它也会 运行 变成 Groovy:

plugins {
    ...
    id ("com.google.firebase.firebase-perf")
}

...

android {
    ...

    applicationVariants.all {
        val variant = this
        val isFirebaseEnabled = !variant.javaCompiler.name.contains("Debug", true)

        gradle.taskGraph.whenReady {
            if (this.hasTask(variant.javaCompiler))
            {
                project.FirebasePerformance.isInstrumentationEnabled = isFirebaseEnabled
            }
        }
    }

    ...
}

请注意,有了这个,transformClassesWithFirebasePerformancePluginFor* 任务对于每个构建变体仍然总是 运行,但是对于没有启用检测的变体,它几乎会立即完成。

现有的所有答案都是有效的,但他们都遗漏了一些东西。

要处理这个问题,您有 2 个主要选项可供选择。

1。使用 firebasePerformanceInstrumentationEnabled 属性

这是 the official way provided by the SDK 本身以在构建过程中禁用它。

这是做什么的:

  • 减少 transformClassesWithFirebasePerformancePluginFor* 任务执行时间到 ~5-10s.
  • 禁用自动跟踪和请求监控,但启用自定义跟踪。您可以使用 AndroidManifest <meta-data> 标记和对 FirebasePerformance.getInstance().setPerformanceCollectionEnabled() 的调用来控制后者。 the docs 中的更多信息。

如何操作:

我认为在极少数情况下当我们需要只启用插件要容易得多(通常只有当我们发布应用程序)而不是在所有其他情况下禁用它。

注意:当然,使用手动构建,您可能会忘记启用它。因此,如果您没有 CI,可能值得在 Gradle 中添加一些其他自动脚本,或者坚持使用其他答案中使用的相反方法。

不过一般来说,我们只需要两步:

  1. 将以下行添加到 gradle.properties 文件:

    firebasePerformanceInstrumentationEnabled=false
    
  2. 在您的 CI 配置或手动构建中使用以下命令:

    ./gradlew assembleRelease -PfirebasePerformanceInstrumentationEnabled=true

优点:

  • 只有一个 属性 可以设置。

缺点:

  • 插件仍然会增加大约 5-15 秒的构建时间。

2。使用自定义 Gradle 项目 属性 以避免应用 firebase-perf Gradle 插件

这是做什么的:

  • transformClassesWithFirebasePerformancePluginFor* 任务根本没有执行。此外,我们还节省了使用第一个解决方案时存在的大约 5-10 秒的额外开销。
  • 与第一种方法相同——禁用自动跟踪和请求监控,但启用自定义跟踪。您可以使用 AndroidManifest <meta-data> 标记和对 FirebasePerformance.getInstance().setPerformanceCollectionEnabled() 的调用来控制后者。 the docs 中的更多信息。

如何操作:

此方法有相似点和警告,也包括两个步骤:

  1. 修改您的应用模块的 build.gradle 文件:

    if (project.hasProperty('useFirebasePerf')) {
      apply plugin: 'com.google.firebase.firebase-perf'
    }
    

    注意:不需要对您的项目应用相同的检查-级别 build.gradle:

    classpath "com.google.firebase:firebase-plugins:$firebase_plugins_version"
    

    当插件本身未启用时,Gradle 不会以任何方式使用此声明。

    如果您使用的是 firebase-plugins v1.1.1 或更高版本 stated in the docs,那么您 不需要 排除 guava-jdk5 依赖项.

  2. 在您的 CI 配置或手动构建中使用以下命令:

    ./gradlew assembleRelease -PuseFirebasePerf

优点:

  • 完全 消除了与 Firebase Performance Gradle 插件相关的时间开销。

缺点:

  • 引入条件检查以在您的 Gradle 脚本中应用插件, 这不是一种惯用的方法。

*(奖励选项)使用自定义 Gradle 项目 属性 排除 firebase-perf SDK

如果您不使用来自 Firebase Performance SDK 的自定义跟踪或任何其他功能,并且仅依赖于自动监控(即您的代码中没有任何对 SDK 的依赖),那么您可以排除此非生产构建的依赖性。

如何操作:

您需要做的就是更新应用模块的 build.gradle 文件:

  • 如果您选择使用第一个选项,则像这样更改您的依赖项:

    if (project.property('firebasePerformanceInstrumentationEnabled') == 'true') {
      implementation "com.google.firebase:firebase-perf:${firebase_perf_version}"
    }
    
  • 如果选择第二个:

    if (project.hasProperty('useFirebasePerf')) {
      implementation "com.google.firebase:firebase-perf:${firebase_perf_version}"
    }
    

优点:

  • 这可能会为您节省一些额外的 ~5-10s,用于配置依赖项和 "ProGuarding"它。

缺点:

  • 您的生产 APK 大小将比调试 APK 大 ~0.5mb。这可能会扰乱您的报告或预测,因此您需要注意这一点。
  • 如果您接近超过 64K 方法计数限制,您可能会突然在生产构建中跨过它并发现自己处于 MultiDex 区域。这意味着要完成额外的工作并测试 运行。这一切都是因为 Firebase Performance 带来了数量惊人的近 5K 方法引用(在应用 ProGuard 进行优化之后)。

您还可以查看 my article 我在其中对这个主题进行了更多扩展。

该线程中的所有评论均有效。我想建议一种非常简单的方法来为调试版本禁用它:

if (getGradle().getStartParameter().getTaskRequests().toString().contains("Release")) {
    apply plugin: 'com.google.firebase.firebase-perf'
}

我已经简化了这个答案的选项 2

  • gradle.properties

    中定义一个属性

    useFirebasePerf=false

  • 禁用性能插件

    if (useFirebasePerf.toBoolean()) { 应用插件:'com.google.firebase.firebase-perf' }

  • 删除依赖项

    if (useFirebasePerf.toBoolean()) { 实施 'com.google.firebase:firebase-perf:16.2.3' }

  • 仅为 CI 构建启用性能监控(我建议仅针对发布构建)

    gradlew assembleRelease -PuseFirebasePerf=true

Firebase Performance 发布了新版本的 perf-plugin (v1.3.0)。这将为特定构建变体启用禁用 Firebase 性能监控Gradle 插件(包括buildTypesproductFlavors).

下面的例子:

 android {
      // ...
    
      debug {
        FirebasePerformance {
          // Set this flag to 'false' to disable @AddTrace annotation processing and
          // automatic HTTP/S network request monitoring
          // for a specific build variant at compile time.
          instrumentationEnabled false
        }
      }
    }

发行说明参考:

https://firebase.google.com/support/release-notes/android#2019-07-10

对于使用 Kotlin DSL 的较新版本的 Firebase perf 插件(1.3.0 及更高版本),您需要添加以下内容:

android {
  ...
  buildTypes {
    ...
    all {   
      with((this as ExtensionAware).extensions["FirebasePerformance"] as FirebasePerfExtension) {
        setInstrumentationEnabled(!isDebuggable)
      }     
    }
    ...
  }

}

对于 Groovy 版本,您可以查看 Firebase documentation

kotlin DSL 中更简洁的方法

buildTypes {
   //My custom extension
   forName("debug") {
      roject.ext.set("firebasePerformanceInstrumentationEnabled", "false")
   }
}

实现 forName

fun <T> NamedDomainObjectContainer<T>.forName(name: String, action: T.() -> Unit) {
    this.maybeCreate(name)
    this.getByName(name, object: Action<T>{
        override fun execute(t: T) {
            t.action()
        }
    })
}