Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The Kotlin and Groovy DSLs should have similar performance characteristics #15886

Open
eskatos opened this issue Jan 20, 2021 · 21 comments
Open

Comments

@eskatos
Copy link
Member

eskatos commented Jan 20, 2021

Expected Behavior

The Kotlin and Groovy DSLs have as much as possible similar performance characteristics.
IOW there's no outlier use case for which the performance characteristics make using one or the other DSL a penalty.

Current Behavior

What follows is the current state of affairs as Gradle 6.8 for four use cases:

  • first use (e.g. ephemeral CI agent or clean workstation without build cache)
  • buildSrc abi change
  • buildSrc non-abi change
  • nothing changes

The data below comes from performance tests run on the Gradle CI. Those tests use a build with a large number of projects and build scripts, the build scripts being rather simple, and they run on both the Groovy and Kotlin DSL for comparison.

Use case Groovy Kotlin Differences
First use 🟢 33.5s 🔴 76.2s Groovy DSL is 2.2x faster
buildSrc abi change 🟢 13.2s 🔴 42.3s Groovy DSL is 3.2x faster
buildSrc non-abi change 🔴 13s 🟢 5.2s Kotlin DSL is 2.5x faster
Nothing changes 🔵 1.7s 🔵 1.8s Similar performance

Context

The numbers above are, at the time of writing, for current release branch of Gradle that is the upcoming 6.8.1. See:

Use Login as guest and note that these links will eventually get outdated.

This issue is a follow up to gradle/kotlin-dsl-samples#902 which resides in an archived repository.

One of the reasons the Kotlin DSL is slower when it is is the time it takes to the Kotlin compiler to compile the scripts.
See https://youtrack.jetbrains.com/issue/KT-24668

@kaushalyap
Copy link

thanks for the benchmark @eskatos

Any issues filed on the youtrack issue tracker against Kotlin compiler related to kotlin dsl performance? if so please link the associated issues.

@LifeIsStrange
Copy link

LifeIsStrange commented Jan 20, 2021

random thoughts from a lambda Kotlin dev:

It could be a useful addition to add a variant for kotlin and groovy on this benchmark:
That could be called e.g Kotlin-optimized and that would enable non-default gradle.properties such as

org.gradle.vfs.watch=true
kapt.use.worker.api=true
kapt.include.compile.classpath=false
org.gradle.parallel=true
org.gradle.caching=true

(btw its unclear whether kapt.include.compile.classpath=false is still useful in 6.8 given compiler avoidance)

Also worth exploring would be to benchmark with the new compiler backend and the new compiler frontend

finally setting a continuous benchmark (in CI) of this would be useful for showing progress and for catching regressions!

note1: I cannot see the linked benchmark results, Login as guest doesn't seems to work (I don't have an account)
note2: reading the guide on how to improve gradle performance:

The Gradle Java plugin allows you to run the compiler as a separate process by using the following configuration for any JavaCompile task:
This process is reused for the duration of a build, so the forking overhead is minimal. The benefit of forking is that the memory-intensive compilation happens in a different process, leading to much less garbage collection in the main Gradle daemon. Less garbage collection in the daemon means that Gradle’s infrastructure can run faster, especially if you are also using --parallel.
It’s unlikely to be useful for small projects, but you should definitely consider it if a single task is compiling close to a thousand or more source files together.

https://docs.gradle.org/nightly/userguide/performance.html#compiler_daemon
This optimization doesn't seems to be provided for Kotlin currently

note3: minor: I wonder whether using the Kotlin BOM incurs a slowdown vs not using it

@gildor
Copy link
Contributor

gildor commented Jan 21, 2021

maybe worth adding one more case, change build.gradle file (not src), I think it even more common comparing to buildSrc

@eskatos
Copy link
Member Author

eskatos commented Jan 21, 2021

Guest access to our CI is currently temporarily disabled, it'll be enabled back soon.

@kaushalyap there's already a link to https://youtrack.jetbrains.com/issue/KT-24668. I'm not aware of other Youtrack issues related to this.

@LifeIsStrange this issue is about the Gradle Kotlin DSL performance, not the Kotlin Gradle Plugin performance in general. For instance KAPT is out of the picture. Also, the embedded Kotlin compiler used internally by the Gradle Kotlin DSL isn't ready to be moved to the new compiler infrastructure. The numbers above represent the default Gradle user experience which is a good thing.

@gildor yes this use case is missing from the set above and I agree it's very common. We started with the buildSrc use case because it potentially invalidates a lot of things and shows the worst situation.

@kaushalyap
Copy link

@kaushalyap there's already a link to https://youtrack.jetbrains.com/issue/KT-24668. I'm not aware of other Youtrack issues related to this.

@eskatos I know about that issue. Hope Kotlin team close that issue in the first half of this year with the movement to new compiler as mentioned in the roadmap, so android devs can move to kotlin dsl for android projects without increased build time.

@gildor
Copy link
Contributor

gildor commented Jan 22, 2021

@kaushalyap This is the new backend of the compiler, it has nothing to do with compilation speed. You probably talk about the new frontend of the compiler, which promises up to 2 times faster compilation, but it will not be ready in 6 months, in the best case it would be some experimental version available this year

@cristan
Copy link

cristan commented Oct 29, 2021

I wonder if this is still an issue. Gradle 7 has been out for a while and it boosts massive performance improvements for Kotlin DSL script compilation. An updated benchmark would be very appreciated :).

@eskatos
Copy link
Member Author

eskatos commented Oct 29, 2021

Those benchmarks are automated and constantly run against Gradle as it evolves. You can browse the results on our CI, e.g. here https://builds.gradle.org/buildConfiguration/Gradle_Master_Check_PerformanceTestSlowLinux_Trigger/46861573?buildTab=report_project55641_Performance

Here I captured the current state:

Use case Groovy Kotlin Differences
First use 🟢 34s 🔴 57.5s Groovy DSL is 1.7x faster
buildSrc abi change 🟢 20.5s 🔴 32s Groovy DSL is 1.6x faster
buildSrc non-abi change 🔴 21s 🟢 4.3s Kotlin DSL is 4.8x faster

Things indeed got better since Gradle 7, especially the non-abi change scenarios. The performance isn't similar though.
The Groovy DSL got slower in general since Groovy 3.
The Kotlin DSL is still almost twice slower in first use and abi-change scenarios.
The Groovy DSL is now much slower than the Kotlin DSL in a non-abi change scenario thanks to compilation avoidance introduced in the Kotlin DSL. This can be added to the Groovy DSL too to make it faster in such scenarios, see #14829.

@kaushalyap
Copy link

@eskatos Thanks for the update, I wonder what would be the build times for composite builds for the same project?

There is an issue reporting converting buildSrc to implicit included.

@rowi1de
Copy link

rowi1de commented Dec 9, 2021

Could you explain what ABI / Nop-ABI means 🙈

@eskatos
Copy link
Member Author

eskatos commented Dec 9, 2021

@rowi1de sure thing!

ABI stands for Application Binary Interface.

An ABI change is a change that modifies the ABI, iow the "public api" that downstream consumers compile against. All consumers need to be recompiled.

A non-ABI change is a change that does not modify the ABI, iow only touches the "private implementation". Consumers compilation can be skipped.

@blundell
Copy link

blundell commented Feb 10, 2022

@eskatos clicked your like this one and after signing in a guest I get:

Build with id "46861573" does not exist

( was hoping to check the latest benchmarks :) )

@eskatos
Copy link
Member Author

eskatos commented Feb 10, 2022

@blundell that individual run got garbage collected, here you can see the list of runs https://builds.gradle.org/buildConfiguration/Gradle_Master_Check_PerformanceTestSlowLinux_Trigger?branch=master&buildTypeTab=overview&mode=builds

@blundell
Copy link

blundell commented Feb 11, 2022

I think I've done this right :D

Gradle 7.4/7.5 numbers
(buildSrc = 7.4, First use = 7.5)

Use Case Groovy Kotlin Difference
First use 🟢 38.855s 🔴 63.54s Groovy DSL is 1.6x faster
buildSrc abi change 🟢 25.307 🔴 35.014s Groovy DSL is 1.4x faster
buildSrc non-abi change 🔴 24.526s 🟢 4.732s Kotlin DSL is 5x faster

Info from 11th Feb 2022 CI run

For example, from the performance tab, I looked up the buildSrc abi change and took the first row, here.
Kotlin:
image
Groovy:
image

and the first use numbers from here.
Groovy:
image
Kotlin:
image

@eugene-krivobokov
Copy link

@blundell , could you please explain the difference calculations?

In the previous results: 21s VS 4.3s - 4.8x faster. I get it.
In the last results: 24.526s VS 4.732s - 135% faster. How have these percents been calculated?

@blundell
Copy link

@eugene-krivobokov Sorry about that, wrong equation. Updated to calculate as a percentage.

@mochadwi
Copy link

@blundell that individual run got garbage collected, here you can see the list of runs https://builds.gradle.org/buildConfiguration/Gradle_Master_Check_PerformanceTestSlowLinux_Trigger?branch=master&buildTypeTab=overview&mode=builds

does it private? seems unable to open with my team city account

@liutikas
Copy link
Contributor

Is there any sort of break down on what goes in "first use" and why it is so much slower?

@stigkj
Copy link
Contributor

stigkj commented Aug 27, 2022

@liutikas I guess "first use" is slower with Kotlin DSL as that needs to be compiled.

s097t0r1 added a commit to s097t0r1/ktcast that referenced this issue Dec 17, 2022
build.gradle.kts configuration files was replaced by build.gradle

# Ref: gradle/gradle#15886 (comment)
s097t0r1 added a commit to s097t0r1/ktcast that referenced this issue Dec 17, 2022
* build: speed up build time (part 1)

# Ref: https://habr.com/ru/company/yandex/blog/678786/

* build: speed up build time (part 2)

build.gradle.kts configuration files was replaced by build.gradle

# Ref: gradle/gradle#15886 (comment)
@eskatos
Copy link
Member Author

eskatos commented Feb 16, 2023

Here are numbers updated for Gradle 8.0

Use case Groovy Kotlin Differences
First use 🟢 30s 🔴 75s Groovy DSL is 2.5x faster
buildSrc abi change 🟢 9s 🔴 35s Groovy DSL is 3.8x faster
buildSrc non-abi change 🔴 9s 🟢 5.5s Kotlin DSL is 1.7x faster
configuration 🟢 1.9s 🔴 2.2s Groovy DSL is 0.15x faster

This is not looking great. The upgrade to Kotlin 1.8 in Gradle 8.0 caused a regression in Kotlin DSL script compilation. Also those scenarios are not the best at representing reality as they don't even use the plugins {} block for which Gradle 8.0 can provide a 20% performance boost. This would not make the overall build times faster than with the Groovy DSL though.

The gap is not just the Kotlin compiler performance change. Groovy got faster. There are also some changes due to other areas of Gradle at play. But there definitely was a performance regression with 1.8 in our isolated tests. We are discussing this with the compiler team and will try to mitigate.

@Jacks0N23
Copy link

@eskatos could you please check gradle 8.1 performance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests