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?
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:
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.
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:
- There are a lot of
!!.accesses to satisfy Kotlin on the null-safety
- Some additional locals are introduced in the methods/constructors to comply with the immutable method parameters of Kotlin.
- I also use some custom extension methods to add required functionality on built-in types and collections.
- There are a lot of type conversions happening. TypeScript only has the type
numberwhich 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.
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.