Closed zakhenry closed 2 years ago
This seems like potentially an issue with Kotlin itself, given where it's crashing, and the evidence that the Java API compiles as you expect. The Kotlin bindings are a wrapper around the Java API, so this feels likely related to Kotlin's compiler itself, and less about Protocol Buffers.
Yea I did wonder that, though it could potentially be that there is a particularly inefficient generated code structure being used with the protobuf generated code. I'll post a ticket in the kotlin issue tracker too to see what they say.
I am not super aware of how the system deals with cross-language bindings (Java/Kotlin) so perhaps this is triggering an unfortunate case in the compiler itself?
Yep that sounds plausible, unfortunately I'm pretty new to JVM languages so don't really know where to start to dig into myself.
I've raised https://youtrack.jetbrains.com/issue/KT-47270 to correspond with this issue.
Hopefully one of these two projects can identify where the fix needs to happen because it would be a huge shame to miss out on the amazing new DSL that would clean up our protobuf bindings massively
I also find myself wondering if this could be addressed by a more incremental build: splitting the protos up between more files or more build units.
I wonder if there are JVM flags that could be set to make this perform better?
https://dev.to/martinhaeusler/is-your-kotlin-compiler-slow-here-s-a-potential-fix-4if4 looks like it has something that is worth trying
Hi, we're facing an issue with the same combination: Kotlin + Protobuf, not with large but a lot of .proto files. In my computer setting XMX for kotlinc worked but it didn't when tried to do the same using a Docker gradle container.
according to Kotlin this has been repro'd on their end: https://youtrack.jetbrains.com/issue/KT-47270
Any additional solutions are blocked on whatever they end up doing.
We are looking into this issue more, but for now the best workaround is to configure a higher memory limit.
The root of the issue is that the representation of Java source files is quite ineffective in Kotlin compiler, so when we read huge generated 18 MBs HelloWorld.java it leads to high memory footprint.
Potentially, more than 68% of the heap is allocated for the pieces of that file. To be honest, I don't think it's possible to replace the representation soon, so I'd suggested as a workaround if it's possible to compile HelloWorld.java before running kotlinc and then supply it in a form of a class-file. But unfortunately, I'm not sure there is a possibility to have such a workaround via gradle/protobuf infrastructure.
BTW, there is another workaround, namely putting this to build.gradle:
compileKotlin {
kotlinOptions.freeCompilerArgs += ['-Xuse-javac']
}
But this compiler flag (enabling a different internal representation for Java) is still very experimental and unfortunately we can't give any guarantees it would work correctly in every environment.
Closing this since it's being tracked with jetbrains.
I work with a decent sized protobuf definition (68 files, 650 messages, 1875 fields) and am currently using Kotlin gRPC but with the java protobuf api and was excited to switch to the shiny new DSL based Kotlin generated code but alas it crashes out of memory. I've included a minimal reproduction in a separate repo below
What version of protobuf and what language are you using? Version: 3.17.3 Language: Kotlin
What operating system (Linux, Windows, ...) and version? MacOS 11.4 (Intel)
What runtime / compiler are you using (e.g., python version or gcc version) Kotlin 1.5.10
What did you do? Reproduction also outlined in https://github.com/zakhenry/kotlin-protobuf-oom-reproduction
I created a protobuf file with 300 messages, each with 10 string fields, and tried to compile a simple Kotlin main function that uses one of them.
What did you expect to see
It should compile.
What did you see instead?
The compilation step crashed out of memory:
Anything else we should know about your project / environment
Notably, using just the Java compiled protos in my machine completes the compilation in 13 seconds. See branch https://github.com/zakhenry/kotlin-protobuf-oom-reproduction/tree/java-api-only to try it yourself.