-
Notifications
You must be signed in to change notification settings - Fork 228
Add experimental Kotlin incremental compilation #1316
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
base: master
Are you sure you want to change the base?
Conversation
0e33330
to
9fe2ada
Compare
errStream: java.io.PrintStream, | ||
vararg args: String, | ||
): ExitCode { | ||
System.setProperty("zip.handler.uses.crc.instead.of.timestamp", "true") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need to set this, or is this pulled from the K2JVM impl?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pulled from BazelK2JVMCompiler. It hits the same internals as the existing implementation on the Kotlin side, and figured if it was still needed there, it may be needed here.
// The incremental directory is roughly analogous to a Gradle transform cache directory. Must be unique per compilation target. | ||
val incrementalDirectory = Paths.get("").toAbsolutePath().parent.resolve("_kotlin_incremental/$label/$incrementalId").toFile() | ||
|
||
val kotlinService = CompilationService.loadImplementation(this.javaClass.classLoader!!) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible/safe to keep the CompilationService implementation around?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean simply not loading it every compile task? I'm sure that's safe, yeah.
b05d750
to
bbd1f67
Compare
Replace commented out snapshot generation code Add new jar dependencies needed for incremental compilation Temporarily force persistent working directory for incremental compilation
bbd1f67
to
eec887d
Compare
Invalidate snapshot when underlying (abi) jar changes
Note
This is presented as a POC, but nowhere near merge-ready. In its current state, it may compile your apps and you may see significant build time improvements.
This adds an experimental implementation of incremental compilation via the new "Build Tools API" (BTAPI). The BTAPI itself can replace the direct usage of
K2JVMCompiler
, but is also required to leverage incremental compilation.Initial Design
In short:
BazelK2JVMCompiler
namedBuildToolsApiCompiler
. This invokes the BTAPI.<output base>/execroot/_kotlin_incremental/
)build_tools_api
to enable building with the new BTAPI (only)incremental_compilation
to then add incremental compilationThe rest is fairly trivial usage of the BTAPI, a little of which requires some tinkering and tribal knowledge to know how exactly it is supposed to be used. I did my best to document my knowledge, with brevity.
Performance
The main driver of performance gains are incremental builds that only build a subset of Kotlin files in a target. The incremental data passed in to subsequent builds gives an additional level of work avoidance beyond the action-based caching in Bazel.
I hope to get more comprehensive numbers, but our main test case was a sample incremental build that was ~4x faster in Gradle due to only needing to recompile very small slices of a chain of Kotlin modules. With incremental, Bazel matches what we see with Gradle.
4x isn't a fixed number, it could be greater or smaller depending on how many Kotlin files are in how many dependent targets, and how many files can skip compilation based on the affected classpaths in a build.
TODO
CompilationTask
. It works, but not idea.