Analyze slow Kotlin compilation

Hi everyone.

tl;dr: How can I find why the Kotlin compilation of my project is so slow compared to other compilers? Are there any flags beyond --scan which will produce detailed logs?

Problem
I am developing a multi platform library written in TypeScript. Via a custom transpiler toolchain I target multiple platforms like Web, .net and Kotlin. Now as I have finished the Kotlin toolchain I was surprised by the slow compilation of my codebase in Kotlin. I found similar posts about the fact that Kotlin could be slow in compilation but I did not really find a good guide on how I can find out why this is the case.

What is the best approach to find out why the Kotlin compilation is slow? I tried to use the --scan Gradle option but It just tells me on task level which parts are taking time. I would like to dig deeper into the following tasks which seem to be the main players:

  • compileCommonMainKotlinMetadata
  • compileKotlinJvm
  • compileKotlinMetadata

So far I guess the error is within my codebase and not Kotlin in general, but I have no clue how to find which part is causing the time. I’d appreciate any help on how I can dig deeper here. Maybe with generating my code a bit different, I can boost the compilation.

Project details
Most of my Kotlin code is transpiled from TypeScript and follows the coding patterns from this language. Obviously many things could be written maybe more efficient if everything would be written in Kotlin directly but that’s not possible. The transpiler mainly reorganizes some syntax parts to play well with the Kotlin rules. There are four main parts which might make the compiler suffer a bit:

  1. There are a lot of !!. accesses to satisfy Kotlin on the null-safety
  2. Some additional locals are introduced in the methods/constructors to comply with the immutable method parameters of Kotlin.
  3. I also use some custom extension methods to add required functionality on built-in types and collections.
  4. There are a lot of type conversions happening. TypeScript only has the type number which can hold 64bit floating points but still plays well with integer arithmetics like bit-ops. To ensure everything works with the strict number type rules of Kotlin I need to cast rather often.

So far I am only targeting JVM but I plan to ship my library to Android and iOS via the Kotlin targets.

Times
Here an example compilation run of my project. The essential numbers are:

  • TypeScript: Compiles in 59secs (custom code generation + minimized output + raw output)
  • C#: Compiles in 2m 3s where the actual compilation of the C# codebase takes 1m 15s, the rest is code generation and transpiling.
  • Kotlin: Compiles in 7m 4s where the actual Gradle assemble tasks take 6m 11s.

It’s more or less the same codebase on C# and Kotlin but Kotlin takes 5min longer to compile.

If anyone would like to check out the code locally Node.js needs to be installed and these commands need to be executed on the CLI. Once done, you can also open the project (src.kotlin\alphaTab) in IntelliJ IDEA. Upon request and interest I could also push the generated code to a separate branch for easier tests.

Cheers
-Daniel

3 Likes

Does really nobody of the Kotlin Team or Community have an idea on this. Does this simply mean there is no way to find out why the compiler is so slow compared to other compilers?

I would really like to help you there but I never really had many issues with compile speed. What I notice is that initial compilation in kotlin can be quite slow but kotlin is really good in caching results so that recompiling is quite fast. I doubt that the possible reasons you listed are the main cause for the slowdown.

Not sure, but if you want to dive deeper into this I suggest you join the kotlin slack (https://kotl.in/slack). There are much more people who actually undestand the compiler compared to here. While there are some members of the kotlin team active in this forum they aren’t that active here, it’s mostly just the community although I’m guessing they are reading through the language-design topics at least.

1 Like

@Wasabi375 Thanks a lot for your reply. Unfortunately in a CI/CD environment you typically always have clean builds. I could try to use the caching mechanisms on GitHub Actions but it feels more like a workaround than a proper solution. I will hop over to the Kotlin Slack and check if they have some ideas. I also saw that in Kotlin 1.5 a completely new compiler is a key priority. And it aims for better performance :tada:, but still it would be great to find out what’s happening there in 1.4

I also have that problem, my compiler 20 to 30 seconds to compile my code. I just hope the executables will not be this slow when you try to run the app