Kotlin logo

Kotlin

A concise multiplatform language developed by JetBrains

Ecosystem

K2 编译器性能基准以及如何在项目中测量性能

Read this post in other languages:

在 Kotlin 2.0.0 版本临近发布之际,K2 编译器现已可供试用!在这篇博文中,我们将探讨 K2 编译器在各种项目中的性能,并为您提供收集性能统计信息的工具。

K2 编译器经过很长时间才达到稳定版。 决定从头重写编译器后,我们添加了新的类型推断算法、新的 JVM 和 JS IR(中间表示)后端,以及新的前端。

前端经过根本性更改,开始使用包含更多语义信息的统一数据结构。 这项更改让编译更高效,也让 IntelliJ IDEA 可以更好地分析您的 Kotlin 代码。

Kotlin K2 编译器

这一举措的目标是加快新语言功能的开发、统一 Kotlin 支持的所有平台,以及为 Kotlin 开发者提高性能。

要在 IntelliJ IDEA 中充分利用 K2 编译器的所有好处,请启用 K2 Kotlin 模式。 K2 Kotlin 模式仍处于 Alpha 阶段,因此尚未支持所有 IDE 功能。

关键性能改进

  • K2 编译器将编译速度最高提升 94%。 例如,对于 Anki-Android 项目,干净构建时间从 Kotlin 1.9.23 中的 57.7 秒减少到 Kotlin 2.0.0 中的 29.7 秒。
  • 使用 K2 编译器,初始化阶段速度提高了 488%。 例如,在 Anki-Android 项目中,增量构建的初始化阶段从 Kotlin 1.9.23 中的 0.126 秒缩短到 Kotlin 2.0.0 中的 0.022 秒。
  • 在分析阶段,Kotlin K2 编译器比先前的编译器快 376%。 例如,在 Anki-Android 项目中,增量构建的分析时间从 Kotlin 1.9.23 中的 0.581 秒缩短到 Kotlin 2.0.0 中的 0.122 秒。

设置

我们用来运行性能测试的 Kotlin 项目位于 GitHub 上。 如果您想使用它从 Kotlin 项目中收集统计信息,请参阅收集您自己的测量数据

项目

我们在以下开源项目上进行了性能测试:

工具

我们使用 Gradle Profiler 收集性能测量数据。

我们还使用 Kotlin 构建报告收集有关不同编译阶段的详细测量数据。

测试场景

我们创建了三个场景,涵盖 Kotlin 项目中最常见的编译活动:

  1. 干净构建:我们从头构建整个项目,没有使用预设配置或构建缓存。 第一次编译项目或更改项目配置后,就是这种场景。
  2. 无 ABI(应用程序二进制接口)更改的增量构建:我们更改了一个文件,但这些更改不需要重新编译其他子项目。
  3. 有 ABI 更改的增量构建:我们更改了一个文件,但这些更改需要重新编译模块,因为模块的外部接口被修改。

我们比较了从 Kotlin 1.9.23 和 Kotlin 2.0.0 收集的性能数据,并在整个过程中使用 Gradle 8.5。

对于所有场景,Gradle 配置缓存、项目隔离和构建缓存均已禁用。 在收集性能测量数据之前,我们完成了 10 轮预热。 我们总共进行了 10 轮测量。

收集的测量数据类型

除了总的 Kotlin 编译时间和 Gradle 构建时间之外,测试还使用构建报告收集编译器在各编译阶段所花时间的数据:

阶段 描述
初始化 编译器初始化并从编译类路径读取所有可用符号。
分析 编译器逐字符读取源代码,并将其分解为有意义的标记。 对标记进行分析以确定代码结构,然后编译器执行语义检查。
IR 转换 编译器将语义信息转换为内部表示。
IR 降级 编译器将内部表示转换为更简单的形式,并最终对所有特殊语言构造去糖。
IR 生成 编译器将优化的内部表示转换为最终的字节码。

结果

比较不同场景和项目的结果,我们发现 Gradle 的构建速度始终高出至少 9%。 Anki-Android 项目中的改进最为显著,无论编译器场景如何,记录的构建速度都提升了约 20%。

干净构建场景的 Gradle 构建时间图 – Anki-Android 增量构建场景的 Gradle 构建时间图 – Anki-Android

干净构建

新 K2 编译器架构的优势在干净构建场景中最为明显,两个项目在 Kotlin 2.0.0 中的编译速度都显著提高。

Exposed 项目中编译速度提高 80%,编译时间从 Kotlin 1.9.23 中的 5.8 秒下降到 Kotlin 2.0.0 中的 3.22 秒。 同样,Anki-Android 项目的编译器性能提高了 94%,编译时间从 Kotlin 1.9.23 中的 58 秒下降到 Kotlin 2.0.0 中的 30 秒。

干净构建场景的 Kotlin 编译时间图 – Exposed 干净构建场景的 Kotlin 编译时间图 – Anki-Android

深入研究不同编译阶段的性能后,我们发现最大的改进出现在分析阶段,其中 Exposed 和 Anki-Android 项目的速度分别提高了 156% 和 194%。 这直接归功于我们在 K2 前端中新实现的统一数据结构。 由于新编译器只需要管理一个数据结构而不是两个,并且具有额外的语义信息,我们在这里看到如此大的改进并不令人惊讶。

干净构建场景的编译细分图 – Exposed

蓝色 = 分析阶段
干净构建场景的编译细分图 – Anki-Android

蓝色 = 分析阶段

增量构建

对于增量构建场景,编译器性能也有改进。 特别是在 Anki-Android 项目中,两种增量构建场景的编译速度都提高了 275%。

增量构建场景的 Kotlin 编译时间图 – Anki-Android

不过,Exposed 项目的结果并不突出。 有 ABI 更改的增量构建提高了 35%,无 ABI 更改的增量构建则仅仅提高了 7%,因此在这方面还有改进的空间。

调查不同编译阶段的性能时,我们观察到最大的性能提升出现在初始化和分析阶段,在 Anki-Android 项目中两个阶段的速度都提高了 400% 左右。

ABI 场景增量构建的编译细分图 – Anki-Android 
无 ABI 场景增量构建的编译细分图 – Anki-Android

同样,Exposed 项目在初始化和分析阶段表现出较小的改进,性能提升了 12%–55%。 对于 IR 降级和 IR 生成阶段有 ABI 更改的增量构建,实际上存在性能下降。 不过,这些阶段花费的时间起初就很短,因此我们认为影响微乎其微。 例如,在 Kotlin 1.9.23 中,IR 降级阶段需要 0.01 秒,在 Kotlin 2.0.0 中上升到 0.014 秒。

收集您自己的测量数据 

随着 Kotlin 2.0.0 的发布日期越来越近,K2 编译器已经成为备受瞩目的焦点,现在您可以亲自上手尝试。 本节将指导您收集自己的 Kotlin 项目性能统计信息。

为了让您能够对自己的 Kotlin 项目进行快速基准测试,我们专门准备了一个性能管理工具。 这是一个基于 Kotlin 的项目,允许您收集任何 Kotlin 项目(本地或远程)的性能测量数据。 默认情况下,此项目运行适用于 Kotlin 1.9.23 和 2.0.0-RC1 的基准测试。 但是,您可以根据需要自定义测试场景。 出于可视化目的,您可以分析这些场景生成的原始数据,也可以使用提供的 Kotlin Notebook 获取更方便的可视化表示。

第 1 步:在 IntelliJ IDEA 中打开项目

  1. 克隆 k2-performance-metrics 仓库
  2. 下载并安装最新版本的 IntelliJ IDEA
  3. 在 IntelliJ IDEA 欢迎屏幕上,点击 Open(打开)或在菜单栏中选择 File | Open(文件 | 打开)。
  4. 导航到 k2-performance-metrics 文件夹,点击 Open(打开)。

第 2 步:设置项目

  1. 验证环境变量:
    1. 确认 JAVA_HOME 变量已设置,因为它将用于编译项目。
    2. 如果项目涉及 Android 开发,确保已设置 ANDROID_HOME
  2. gradle.properties 文件中,通过以下方式之一添加要收集测量数据的项目:
    • project.path 中添加本地路径。
    • project.git.url 中添加 GitHub URL,并在 project.git.commit.sha 中添加您希望测试运行的提交。
  1. 对于增量构建场景,添加要更改的文件的路径:
    1. 有 ABI 更改的增量构建场景为 scenario.abi.changes
    2. 无 ABI 更改的增量构建场景为 scenario.non.abi.changes

第 3 步:收集测量数据

  1. 在 IntelliJ IDEA 中,选择 View | Tool Windows | Gradle(视图 | 工具窗口 | Gradle)打开 Gradle 工具窗口。
  2. Tasks | benchmarks(任务 | 基准)中,选择并运行 runBenchmarks 任务。
在 Tasks | benchmarks(任务 | 基准)中,选择并运行 runBenchmarks 任务

或者,您也可以从 k2-performance-measurement 根目录在终端中运行以下命令:

./gradlew runBenchmarks -t

默认情况下,构建报告位于 reports/{kotlin-version}/{scenario-name} 文件夹中。

如果您想创建自己的自定义测试场景,可以扩展 build.gradle.kts 文件中的任务类。 有关详情,请参阅 k2-performance-metrics 仓库的 README.md 中的“创建自定义构建场景”部分

第 4 步:使用 Kotlin Notebook 分析结果

您需要 IntelliJ IDEA Ultimate 才能使用 Kotlin Notebook

  1. 在 IntelliJ IDEA 中,转到 Settings/Preferences | Plugins(设置/偏好设置 | 插件)并选择 Marketplace 标签页。
  2. 在搜索栏中,搜索“Kotlin Notebook”并选择 Install(安装)。
  3. 打开 benchmarkResult.ipynb 并点击装订区域中的 Run All(全部运行)按钮运行所有单元。
全部运行

结论

新的 K2 编译器架构可以显著减少项目的编译时间。 这在干净构建和编译的分析阶段尤其明显,尽管新编译器也缩短了 Gradle 构建时间。 不过,实际的改进程度将取决于具体项目。 某些项目的性能可能会大幅提升,某些项目可能只会略有改进。

在开发新 K2 编译器的过程中,我们一直在内部项目中测试其性能。 此外,EAP Champion 和早期采用者也在自己的项目中进行了测试,为其性能和实用性提供了宝贵的反馈。 

现在,我们邀请您尝试 K2 编译器并提供反馈。 我们欢迎您加入我们公共 Slack 中的 #k2-early-adopters 频道(在此处获取邀请)获得支持和参与讨论。  如果您遇到问题或 bug,请随时在 Kotlin YouTrack 项目中创建问题。 您的反馈对于完善 K2 和确保其符合社区的高标准和需求至关重要。

更多文章和视频

本博文英文原作者:

Sue

Sarah Haggarty

image description

Discover more