【问题标题】:Firebase Performance Plugin causing slow build timeFirebase 性能插件导致构建时间缓慢
【发布时间】:2018-05-02 23:51:20
【问题描述】:

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

Slow Build shown in Profiler

【问题讨论】:

  • 在 Android 上使用 Firebase Performance 时有一个编译后阶段。它必须查看您应用程序的所有类文件。这是正常的。
  • @DougStevenson 是否可以不这样做并在某些版本中使用无操作变体?例如开发期间使用的调试版本?

标签: java android firebase android-gradle-plugin firebase-performance


【解决方案1】:

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

应用程序:

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

root/buildscript/依赖项:

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

【讨论】:

  • 谢谢你这工作完美。使用此修复程序,我的构建时间也减少了 41%。
  • 你认为我们可以使用构建风味作为标志吗?例如if (!BuildConfig.Debug) 然后启用性能监视器? - 谢谢
  • 不,此开关要么加载插件,要么将其从类路径中完全删除。
  • 对我来说,它破坏了 UI 测试,我在运行 UI 测试时遇到错误“未找到测试错误,空测试套件”
  • 我认为 v1.1.1 或更高版本不需要像 stated in the docs 那样排除 Guava。此外,没有必要在类路径声明中添加条件语句。如果您不应用插件,Gradle 将不会以任何方式使用它。
【解决方案2】:

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

要处理此问题,您有 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 脚本中应用插件,some might argue 这不是惯用方法。

*(奖励选项)使用自定义 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-10 秒,用于配置依赖项和 “保护”它。

缺点:

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

您也可以查看my article,我会在此详细介绍此主题。

【讨论】:

【解决方案3】:

Firebase Performance 发布了新版本的perf-plugin (v1.3.0)。这将启用禁用 Firebase Performance Monitoring 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

【讨论】:

  • 有了这个解决方案,gradle 同步失败,ERROR: Could not find method FirebasePerformance() for arguments [...]。性能插件是 v1.3.1。还有 firebase-perf:18.0.1 或 firebase-perf:19.0.0。我将配置粘贴到 android -> buildTypes -> debug 中。 Android Studio 版本为 3.4.2。其他人有同样的问题吗?
  • 我错过了添加或重新添加apply plugin: 'com.google.firebase.firebase-perf'。 Gradle 同步成功完成
【解决方案4】:

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

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

【讨论】:

    【解决方案5】:

    只是给另一个选项来禁用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'
    }
    

    【讨论】:

    • 我认为 v1.1.1 或更高版本不需要像 stated in the docs 那样排除 Guava。此外,没有必要在类路径声明中添加条件语句。如果您不应用插件,Gradle 将不会以任何方式使用它。
    【解决方案6】:

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

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

    如果你能正确地应用插件,有条件地应用插件似乎确实有效,但这不是官方支持的功能。再往下看,还有一点:

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

    果然,Firebase 插件实际上公开了一个属性,可让您打开或关闭检测(因此切换增加的构建时间)。但是,使用此属性很棘手,因为您必须在构建过程中在正确的时间应用它,但是一旦您掌握了它,您就可以基本上将其旋转到您想要的任何位置。

    以下代码 sn-p 是我们如何根据调试与非调试构建变体来旋转检测。它是用 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* 任务仍将始终针对每个构建变体运行,但对于未启用检测的变体,它几乎会立即完成。

    【讨论】:

    • 这是一个不错的选择。但是,具有 firebasePerformanceInstrumentationEnabled=false 属性的构建仍然比禁用 firebase-perf 插件的构建慢 5-15 秒。
    • 5-15 秒实在是太多了。在调试构建时,Gradle 插件最多需要几毫秒。它应该是无操作配置。如果没有,它只是一个糟糕的插件。我使用了一个类似的标志来只在我们的 CI 中启用它,并且像一个魅力一样工作。
    • @tasomaniac 我同意,我也不喜欢它。这只是我尝试以最“受支持”的方式(至少从我当时能找到的方式)来缓解问题,即不有条件地应用插件,同时仍然显着减少调试构建时间。
    【解决方案7】:

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

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

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

    【讨论】:

    • 更简洁的版本:extensionByName<FirebasePerfExtension>("FirebasePerformance").setInstrumentationEnabled(!isDebuggable)
    【解决方案8】:

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

    • 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

    【讨论】:

    • 这是 option 2bonus option 的结合,但也有一个额外的设置步骤,即在 gradle.properties 中定义属性。所以我会说这有点复杂而不是简化。
    • @qwertyfinger 它是可见的并且与定义的其他布尔 gradle 属性一致:) 也不会重复 project.hasProperty('useFirebasePerf')。你在解释一切方面做得很好!
    • @android_dev,只要有条件地将工件添加到类路径中,这是否意味着非发布版本不会解决依赖关系?您是否引入了用于调试的无操作版本和用于发布构建的真实版本的抽象?
    • @azizbekian 这实际上只是它的外观示例。默认情况下,每个构建都禁用它。我们有不同的 CI 构建,其中一些包括性能监控,一些没有。对于调试版本,如果需要,我们也可以使用它。 gradlew assembleDebug -PuseFirebasePerf=true
    【解决方案9】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-25
      • 2015-02-13
      相关资源
      最近更新 更多