I've ported a lot of services from kotlin to rust. In my experience the kotlin code is about half the size of rust, and has about 200 mb + 2*x the memory overhead. Kotlin code probably takes about half of the time (or less) to write compared to rust as well, but you're not quite as sure that is it bug free as the rust code once it's done.
That's a great point and I'm not sure why the memory usage/performance didn't come to mind when writing this.
It's probably because, like most JVM related things, it fits into the "good enough" bracket. Most things running in the JVM are definitely not on the forefront of either CPU or memory performance.
I haven't done personal estimates, but your 200 mb + 2*x estimate feels in line to what I'd expect when compared to "memory-tight" languages.
I agree and I'm not sure what language I would choose myself if it was up to me. In reality, we deployed to kubernetes with redundant instances and memory usage was the limiting factor with kotlin and it would not have been with rust.
Im curious :) Why did you port the services from Kotlin to rust? Can you elaborate a bit on the reasons for the rewrite?
I just like programming and I ported what I wrote at work to rust in my spare time. Basically I was thinking about if rust would be viable at work and in my spare time I tested the hypothesis.
An important distinction is also whether you were using Kotlin-JVM or Kotlin-native. I'd imagine the native version doesn't have the same memory impacts. (But you also don't get the JVM advantages).
While I didn't try kotlin native, I did try porting the micro service from spring boot to micronaut + graalvm native and the memory usage was pretty much identical to spring boot.
While the KMP story specifically is still pretty rough, supporting native and JS (or WASM) is becoming table stakes for new languages. Go, Rust, Gleam, even C all support some version of this. Now that there’s a common system API available across all the platforms, all the UI/database/network/whatever application libraries and frameworks can be unified as well. Multiplatform of today is closer to targeting different architectures (like x86 vs x64, which has worked since the dawn of time) compared to, say, Xamarin of yesteryear which abstracted over various native UI libraries.
Kotlin backend dev of 7 years here (never done Android). Here my 50 cents to some of the "bad" points: 1) tenary operator. Apart from the "if-else is an expression" defence there's also the fact the in Kotlin the '?' is linked to nullability, not only conceptually but also in regards to parsing Kotlin code. There's a video on youtube where the first Kotlin language designer said that he once - because so many people were asking for it - actually sat down and tried to my the "a ? b : c" syntax work, but couldn't because of ambiguity (I think the issue was interaction with nullability operators, but I could be wrong). 2) return inside lambda. There is actually an option that allows for normal returns, but it's not very idiomatic (to a degree where I myself forgot that this option exists until a few months ago) and that is to instead of providing a lambda as a parameter, you can always provide an anonymous function instead (https://kotlinlang.org/docs/lambdas.html#anonymous-functions). In anonymous functions a return works like you're used to, but but the whole code gets more verbose. Here's an example: https://pl.kotl.in/4NQ4lMasf 3) Destructuring is worthless without naming. I visited the KotlinConf2024 and in one talk they said there are going to fix this (Kotlin 2.3??), probably in this one https://www.youtube.com/watch?v=tAGJ5zJXJ7w&list=PLlFc5cFwUn... 4) Coroutines. If I'm writing a Spring app, I (generally) don't use those as well. The exception was an reactive Spring with Webflux app that I converted from Java to Kotlin where the native coroutines constructs were just nicer (and more secure thanks to structured programming) than using Mono/Flux (see https://www.baeldung.com/kotlin/spring-webflux-kotlin). But I use Ktor in several of my newer apps and there coroutines are the only option. I admit that I struggled for a long time with coroutines. I read a tutorial or official documentation here and there, got the gist of it, but things got fuzzy soon enough. But I want to recommend the 3rd chapter of the 2nd edition of "Kotlin in Action". This is the best description of coroutines I've ever read and I finally got the feeling that I understood the whole thing! https://www.manning.com/books/kotlin-in-action-second-editio...
In Raku the ternary was changed to ‘exp ?? True !! False’ to free up the single characters ‘?’ and ‘:’ for other purposes.
IME it’s not such a large shift for the developer (still easily recognizable as a ternary) while also having the benefit of slightly increasing the visibility of ternary expressions in the coding experience.
Edit: Thanks for the coroutine reading recommendation. I’ve been struggling a bit with them and have a few in use but would definitely like to grok them better.
I'm actually in team no-ternary operator in Kotlin, simply because there shouldn't be two ways of doing the same thing. Maybe the problem is a linter issue: for me the main point of the ternary operator to have a very concise expression, a one-liner. But maybe our linters warn when a) we use if-else without braces and b) we put everything on the same line!?? Btw there is already another way to write the ternary operator in Kotlin (assuming the positive-case value of expression X is non-nullable): "C ? X : Y" -> "X.takeIf { C } ?: Y" https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/take-if... Though I admit, I've never used this version either.