utopia-rise / godot-kotlin-native

Kotlin bindings for Godot Engine
MIT License
290 stars 17 forks source link

Is this project dead? #243

Open hojat72elect opened 3 months ago

hojat72elect commented 3 months ago

Hello there.

I was just wondering if this project is going to be archived or do you intend to come back to it and keep developing?

I can see that the last commit was (at the time of this writing) 4 years ago and you have also mentioned in the README that cinterop is not an optimal tool. But in the past 4 years a lot has happened. Godot 4 has made it possible to make new extensions for the engine without rebuilding all of it from scratch.

And also, kotlin native and cinterop have been extensively improved in the past few years (KMP is currently stable and Gradle build is supporting it out of the box) so I was really excited to see Kotlin Native (and not Kotlin JVM) on Godot ecosystem.

@chippmann @raniejade I totally understand it's gonna be a big hassle to make it work in a production-level; but I was hoping to get an answer as to if you are going to keep working on it or is this project dead ?

Thanks.

chippmann commented 3 months ago

I don't think we will in the near foreseeable future. There are multiple reasons for that: While back then, our goal was to keep this binding alive, we simply lack the resources to maintain both as this is a huge undertaking and by now, we're only 3 Maintainers; me, @piiertho and @CedNaru (@raniejade is currently not actively contributing anymore as life happens :-) ) and we're all doing this in our free time.

But more importantly (for us at least), while the performance of kotlin native has improved significantly in recent years, it's unlikely that it's anywhere near where we'd need it to be. Although we did not run specific benchmarks again for our use-cases to be fair. But it's very unlikely as the performance would've need to be not 2x or 3x it was back then, but more around 1000x faster than what it was to even come close to the performance we get with the jvm binding. And that seems more than unlikely. @CedNaru might have our benchmarks numbers for kotlin native from back then.

Also while tooling has improved significantly since then, it still cannot compete with the jvm ecosystem and tooling. Specifically when talking about debugging. Debugging kotlin native is still far from ideal.

There are many such problems around still.

Don't get me wrong, I'm a huge fan of KMP and use it extensively at work for Android and iOS and it works awesome there, but I believe it's far from ready for something as performance sensitive as the game development space.

I'm definitely keeping an eye on it and if i find some time, do some benchmarks for our use cases again, but as it stands now, I don't have high hopes.

Besides, the JVM binding is working very well and by now we also support all major platforms. Performance is also very impressive. So my interest lies there atm for this project.

And regarding Godot; we do have plans to move to GDExtension with the jvm project soon. We're currently in the middle of refactoring our core and after that is fully completed, we plan to move to gdextension as well.

But never say never. There might come a time we properly revisit this project. It all depends on time, resources, the circumstances and where kotlin native will be. Hence i would not archive the project as maybe someone want's to continue working on it and spend time on it. So is it dead; from my point of view yes in the sense that we're not actively working on it, and no as i still believe that it could be something viable in the distant future and what we've done so far is a foundation to learn from and not needing to start from scratch.

Mind i ask why you do not consider the JVM binding instead? What from the JVM is holding you back to give that one a chance?

CedNaru commented 3 months ago

Regarding performance, saying it was bad is un understatement. We can't even talk about Python level of bad when we benchmarked Godot + Kotlin/Native. Bunnymark was already reaching 60fps with only 30 bunnies on screen, (vs dozen of thousands with Kotlin/JVM) At the time, I tried as much as I could to optimize this binding but nothing changed, the bottleneck was Kotlin/Native itself. We profiled it at the time and 80% of the CPU was spent on MemoryAllocation (and it was not us spamming Object creation).

A lot changed since then, and I'm confident that if we tried again, the performance would be in an acceptable range today (even if far from the JVM) but like Cedric said, we don't have time for it. I'd like to say that we can reuse a lot of code from the JVM binding, but we actually can't. As you can expect from such project, most of the code in it exist to manage interoperability with Godot C++ code (or C interface in the case of extension). And the JVM and Native got totally ways to do it. For example, all the C++ code would need to be rewritten to Kotlin and even the existing Kotlin/JVM code couldn't be reused either because it's written with the assumption of a JNI binding. So the two would need to be a totally different project.

The Kotlin/JVM project already takes a huge amount of time, so we just can't manage a second that would require as much work for lesser results. For Kotlin/Native to come back to life, 2 main conditions are necessary:

There is also the fact that Kotlin/Native doesn't have that much advantage over Kotlin/JVM when you add tools like Graal native image. The arguments I hear the most about Kotlin/Native are mostly "It's native, so we can avoid GC stalling" and "It's lightweight because no VM footprint". Except it's actually wrong. Kotlin/Native still use a GC behind the hood, being native doesn't anything to its memory management. GCs have a terrible reputation, specially in the world of gaming with of Unity + Mono, but the current JVM has an excellent GC (ZGC), "pause the world" issues are a thing of the past. And with Graal Native Image, we can already make the code native with a much smaller footprint than a regular JVM (at the cost of some performances). The JVM, its tooling and its ecosystem is just that good nowadays.

Kotlin is trying to become its own ecosystem separated from the JVM, and I have no doubt they will manage to do so, KMP is awesome but still impractical for our project. After all, the logic behind KMP is to have a bunch of "universal Kotlin" shared between all targets and a smaller part of your project using a backend specific to a target. But like I explained above, there is close to no code that can be shared between JVM, Native and WASM (if we want to take into account future web exports) because most of our project is about C++ interop and there is no universal interop API in Kotlin, each backend has its own.

Last thing to know. If that project were to come back to life, its use case would be different from the Kotlin/JVM binding. Godot Kotlin/JVM is going to be a gdextension that allows to run Kotlin (and Java) scripts. Godot Kotlin/Native would be a solution to export gdextensions written in Kotlin. A lot of people struggle to understand the difference between scripts and extensions because from a user point of view there is some overlap between the two. But from a technical point of view, extensions and scripts are totally different concepts.

chippmann commented 3 months ago

Found the old benchmark data: https://github.com/utopia-rise/godot-kotlin-jvm/tree/master/harness/bunnymark At the bottom of the page you find the results from the bunnymark running with kotlin/native and above (outdated) numbers of the jvm version both running on a jre and with graal native image.

hojat72elect commented 3 months ago

@chippmann @CedNaru Thanks a lot for your informative answers, I loved reading them all. I'm going to let this issue be open so if someone else stumbles upon this repo, they can read it first.