40

在 Android Studio 中使用 Firebase 性能时,gradle 任务app:transformClassesWithFirebasePerformancePluginForDebug所花费的时间比任何其他任务都要长,因此大大减慢了我的 gradle 构建时间。

Profiler 中显示的缓慢构建

4

9 回答 9

60

我们项目中的 Firebase 导致构建时间增加了 40%。为了加快调试构建,我们添加了使用 app/build.gradle 和根 build.gradle 文件中的构建参数打开/关闭它的可能性:

应用程序:

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

根/构建脚本/依赖项:

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 中工作时,将标志添加到编译器选项:

Android Studio 编译器选项

于 2017-12-27T15:26:08.750 回答
39

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

要解决此问题,您有 2 个主要选项可供选择。

1.使用firebasePerformanceInstrumentationEnabled属性

这是SDK本身提供的官方在构建过程中禁用它的方式。

这是做什么的:

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

这该怎么做:

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

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

一般来说,我们只需要两个步骤:

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

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

    ./gradlew assembleRelease -PfirebasePerformanceInstrumentationEnabled=true

优点:

  • 只需设置一个属性。

缺点:

  • 插件仍然增加了额外的约 5-15 秒的构建时间。

2.使用自定义Gradle项目属性避免应用firebase-perfGradle插件

这是做什么的:

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

这该怎么做:

这种方法有类似的点和警告,并且还包括两个步骤:

  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 或更高版本,如docs 中所述,则无需排除依赖项。guava-jdk5

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

    ./gradlew assembleRelease -PuseFirebasePerf

优点:

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

缺点:

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

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

您还可以查看我的文章,我在其中对这个主题进行了更多扩展。

于 2018-11-12T21:43:18.293 回答
28

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

下面的一个例子:

 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

于 2019-07-11T18:35:02.650 回答
17

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

if (getGradle().getStartParameter().getTaskRequests().toString().contains("Release")) {
    apply plugin: 'com.google.firebase.firebase-perf'
}
于 2019-01-14T15:15:50.507 回答
5

只是为了给另一个选项 disable 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'
}
于 2018-07-06T10:47:15.220 回答
5

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

插件不能仅应用于“项目的一部分”。它们要么应用要么不应用。

如果你能做对的话,有条件地应用插件似乎确实有效,但这不是官方支持的功能。在同一线程的进一步下,提出了另一点:

但是该插件应该允许您在更细粒度的级别上对其进行配置。

果然,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*任务仍将始终为每个构建变体运行,但对于未启用检测的变体,它几乎会立即完成。

于 2018-10-15T18:39:07.823 回答
5

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

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

}

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

于 2019-08-11T15:02:42.357 回答
2

我已经简化了这个答案的选项 2 https://stackoverflow.com/a/53270530/1635488

  • 定义一个属性gradle.properties

    使用FirebasePerf=false

  • 禁用性能插件

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

  • 移除依赖

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

  • 仅为 CI 构建启用性能监控(我只建议发布版本)

    gradlew assembleRelease -PuseFirebasePerf=true

于 2019-03-29T05:52:03.923 回答
1

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()
        }
    })
}

于 2020-06-22T09:17:56.983 回答