Kotlin | 为 Kotlin 编译器任务推出构建报告


从 Kotlin 1.7.0 开始,您可以为 Kotlin 编译器任务创建构建报告(Build Reports)。 报告包含不同编译阶段的持续时间以及无法使用增量编译的原因。 此功能目前仍为实验性功能,因此指标列表未来可能会发生变化。


想要调查编译器任务的问题时,构建报告就可以派上用场。 例如,当 Gradle 构建花费过多时间时,难以理解性能不佳的根本原因。 或者,相同项目的编译时间不同:有时需要几秒钟,有时需要几分钟。


Kotlin 构建报告能够比 Gradle 构建扫描更有效地展示问题。 许多工程师使用它们来调查构建性能,但 Gradle 扫描中的粒度单位是单个 Gradle 任务。



如何启用构建报告


要启用构建报告,首先在gradle.properties中声明保存构建报告的输出位置:

kotlin.build.report.output=file

以下值(及其组合)可用:

  • file,将构建报告保存到本地文件中。 默认文件为 ${project_folder}/build/reports/kotlin-build/${project_name}-timestamp.txt

  • build_scan,将构建报告保存到构建扫描的自定义值部分中。 请注意,Gradle Enterprise 插件会限制自定义值的数量及其长度。 这可能导致处理大型项目时丢失某些值。

  • http,使用 HTTP(S) 请求发布构建报告。POST 方法以 JSON 格式发送指标。 数据可能因版本而异,请在 Kotlin 仓库中查看已发送数据的当前版本。

如果您没有 HTTP 端点,请使用以下示例之一:

1. 基于 ELK 堆栈的 HTTP 端点。 安装 Elasticsearch 实例并为 Logstash 使用以下配置:

input { 
    http {}
}
filter {
   date {
        match => [ "timestamp""yyyy-MM-dd'T'HH:mm:ss" ]
        timezone => "UTC"
        target => "@timestamp"
    }
    mutate { remove_field => [ "http""url" ] }
}
output {
    elasticsearch {
        index => "kotlin_reports"
    }
}



2. 基于 Kotlin 的 HTTP 端点 如果重新编译为 CSV 文件,它将保存编译时长和非增量编译原因的相关信息。


要进一步设置构建报告,请为gradle.properties使用以下选项:

# Required outputs. Any combinations are allowed
kotlin.build.report.output=file,http,build_scan

# Optional. Output directory for file-based reports. Default: build/reports/kotlin-build/
kotlin.build.report.file.output_dir=kotlin-reports

# Mandatory if http output is used. Where to post HTTP(S)-based reports
kotlin.build.report.http.url=http://127.0.0.1:8080

# Optional. User and password if the HTTP endpoint requires authentication
kotlin.build.report.http.user=someUser
kotlin.build.report.http.password=somePassword

# Optional. Label for marking your build report (e.g. debug parameters)
kotlin.build.report.label=some_label



如何阅读构建报告


这里的优化过程很有创意。 现成指南经常很难提供,您需要具体情况具体分析。 但有时,您可以使用以下管道获得良好结果:

  1.  了解构建并非增量的原因并修正底层问题。

  2. 如果增量编译需要过多时间,可以重新组织源代码文件。 例如,不将所有类打包在一个文件中,不将所有顶级函数声明在一个文件中,等等。

我们来看一看生成的构建报告。 执行这个任务花费了将近 40 秒:

Task ':kotlin-gradle-plugin:compileCommonKotlin' finished in 39,73 s
Compilation log for task ':kotlin-gradle-plugin:compileCommonKotlin':
  Non-incremental compilation will be performed: UNKNOWN_CHANGES_IN_GRADLE_INPUTS
Time metrics:
  Total Gradle task time: 39,73 s
  Task action: 0,09 s
    Calculate output size: 0,01 s
    Run compilation: 39,32 s
      Incremental compilation in daemon: 39,27 s
        Update caches: 0,40 s
        Sources compilation round38,57 s
  Compiler initialization time1,02 s
  Compiler code analysis: 26,36 s
  Compiler code generation: 10,87 s
Size metrics:
  Total size of the cache directory6,2 MB
    ABI snapshot size49 B
  Total compiler iteration: 1
Build attributes:
  REBUILD_REASON: Unknown Gradle changes


Total Gradle 任务时间显示了从任务执行到侦听器通知的时间。 任务操作仅指示在 Gradle 工作进程中安排编译作业的任务。 编译本身在 Gradle 工作进程中执行。 您可以在运行编译部分查看其编译时间。


我们看到这个模块是以非增量方式构建的,因为 Gradle 无法计算输入之间的差异。 这通常发生在干净构建中或在构建脚本中执行了更改时。 由于增量编译不可用,几乎所有时间都花在了代码分析上。


编译无法增量的最常见原因:

  • DEP_CHANGE_HISTORY_NO_KNOWN_BUILDS– 这表示先前没有编译某个依赖模块,或者其历史记录文件已被保管起来。

  • DEP_CHANGE_HISTORY_IS_NOT_FOUND– 这表示某个更改的依赖项不是源模块或非 Kotlin 模块。

  • OUT_OF_PROCESS_EXECUTION, IN_PROCESS_EXECUTION– 这表示增量编译可在 Kotlin 守护进程中执行。 其他模式都会强制进行非增量构建。

后续文章将发布关于 Kotlin 增量编译的更多详细信息。 敬请关注!



我们如何在 JetBrains 中

使用构建报告


减少编译时间

以 Space 项目的这个构建报告为例。 我们有一个包含大量生成的源代码文件的模块。 虽然编译是增量的,但 Kotlin 编译器仍然必须在每次更改时重新分析大型源代码文件。

Compile iteration:
    <a large="" generated="" source="" file="">
Time metrics:
  Total Gradle task time108,98 s
  Task action: 0,20 s
    Backup output: 0,18 s
    Connect to Kotlin daemon: 0,01 s
    Calculate output size: 0,01 s
    Run compilation: 108,23 s
      Incremental compilation in daemon: 108,19 s
        Calculate initial dirty sources set0,23 s
          Analyze dependency changes: 0,03 s
          Detect removed classes: 0,19 s
        Update caches: 0,28 s
        Sources compilation round107,49 s
  Compiler initialization time0,12 s
  Compiler code analysis: 80,26 s
  Compiler code generation: 25,04 s
Size metrics:
  Total size of the cache directory: 3,2 MB
    ABI snapshot size: 643 B
  Total compiler iteration: 1


在这种情况下,建议的做法是重新组织源代码:例如拆分大型文件、将不同的类置于不同的文件中、重构大型类等。



跟踪性能回归

Kotlin 团队使用构建报告跟踪多个项目的编译。 我们让开发者为构建报告启用 HTTP 端点,以在一个位置查看总体构建性能。 例如,您可以在 Kotlin 或 Gradle 版本更新后快速检查性能回归并找到运行时间长的编译。



分享反馈


欢迎在您的基础架构中试用构建报告。 如果您有任何反馈、遇到问题或想提出改进建议,请随时在我们的问题跟踪器中报告。 谢谢!


本博文英文原作者:Andrey Uskov


 相关阅读 

《Kotlin 1.7.0 新特性一览》


2022-23 年 Kotlin 团队展望

⏬ 戳「阅读原文」了解更多

本文分享自微信公众号 - JetBrains(JetBrainsChina)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

{{o.name}}
{{m.name}}

猜你喜欢

转载自my.oschina.net/u/5494143/blog/5554379