Kotlin native vs Rust

Did any one tried both languages, if so, what are your observations/comments that can be used to define pros and cons for each one comparing with the other.

2 Likes

Discalimer: I have a little bit experience with Rust, solid experience with Kotlin, no experience with Kotlin Native, but I have some thoughts :wink:

I think the main difference is that you have much more control what the computer actually does in Rust. It is harder to learn and use Rust, but you can squeeze out the last bit of efficiency. Another difference I see is that Kotlin Native is relatively new and immature whereas Rust already has matured a bit (although it is also new compared to it’s main competitor C++). The Rust ecosystem is probably a lot bigger. Kotlin uses garbage collection at runtime whereas Rust checks memory management at compile time. Rust is cleaner in some aspects, because compatibility with the Java legacy (null, abstract class/interface with default methods) was not a design restriction. From a programmers point of view Rust is more functional and less object oriented, you can see this in error handling, pattern matching and the absence of null and classes.

4 Likes

The main difference is memory management system. In Rust memory management is done mostly in compile time. On one hand, it allows to make programs with much smaller memory consumption, on the other hand, it complicated development a lot. Rust and K/N use LLVM as a backend so performance should be more or less the same. The language syntax (excluding borrowing) is similar.

Rust is much older than kotlin, but it did not manage to step outside its initial development niche (web-browser and other memory-critical system applications).I think, that for those you should use Rust. For non-system applications, kotlin has better potential.

6 Likes

From the point of view of a systems programmer, it didn’t complicate development - it picked up a lot of the burden of doing concurrent shared memory programming without shooting yourself in the foot. This is described in detail in Fearless Concurrency with Rust, and it goes straight to Rust’s design goals.

3 Likes

Exactly. Any memory management is better than C/++. Rust has an elegant solution which does not involve additional costs, but from the point of view of application developer any memory management complicates things. Application developer just do not need to think about it. Also in Rust you must think Rust. Borrowing requires a set of patterns which would not exist otherwise.

So for system programmer Rust is a good choice. For anything else, maybe not.

3 Likes

Currently I am working on a GTK+/GStreamer desktop client program. Initially in C++ then I switched to D – D is a much nicer programming language than C++ and the GTK and GStreamer bindings are better. Then the GStreamer people decided Rust was the language of future working so I switched to Rust. Very different to C++, and better. D and Rust are just very different, both have pluses and minuses. The Rust bindings to GTK and GStreamer are good, and they have some futures/channels/executor extensions that make event loop programming nice.

When I look for GTK and GStreamer binding for Kotlin/Native there isn’t anything that gets close to what is available in D and Rust. So no matter how nice the Kotlin language is, Kotlin/Native cannot currently compete with D or Rust in the GTK and GStreamer applications arena.

6 Likes

I’ve just started writing a tool to generate language bindings for libraries which support gobject-introspection, because I think this is really needed. I’ve also tried Rust, and didn’t like it. My main goal is Kotlin Native, which is a better fit than JVM in several ways, but I’m starting with the JVM (using JNA) as a prototype/proof of concept because of Native still being kind of beta-ish with no good support in free editors. I’m hoping a free IntelliJ plugin for Native will appear as part of the multiplatform model.

4 Likes

The Rust gir tool GitHub - gtk-rs/gir: Tool to generate rust bindings and user API for glib-based libraries and the D gir-to-d tool GitHub - gtkd-developers/gir-to-d: Create D bindings from GObject introspection files do a great job of creating GTK+ and GStreamer bindings. The GStreamer community are likely to settle on Rust as the replacement for C it seems. I am not sure what the GTK+ people will do but gtk-rs works nicely as does gstreamer-rs. Having said that I actually prefer D over Rust, and GtkD has excellent bindings to GTK+ and GStreamer.

If Kotlin/Native had a Kotlin binding to GTK+ and GStreamer (rather than just using the C API directly) this would be a Very Good Thing™.

1 Like

There also is java-gnome: java-gnome/src/generator at master · istathar/java-gnome · GitHub

I hadn’t seen java-gnome, but I looked at JGIR. Both look unmaintained; although Java’s fairly stable I guess it’s had some useful new features since those projects were last updated, and certainly the G* libraries will have changed a lot.

I don’t know about java-gnome, but JGIR doesn’t allow you to override a GObject C method in Java, at least not in a straightforward way. I thiink I can achieve that.

Another reason for writing JVM bindings in Kotlin instead of Java is that g-i has nullable tags, it would be a shame not to take advantage of them.

1 Like

Java-gnome uses same .defs files as gtkmm, you can download fresh ones and regenerate, link above points to generator.

The problem there is that the gtkmm binding is hand crafted, it is not generated from the GIR files – as far as I know.

If you are interested in Kotlin/Native because of performance, you really should choose something else. Kotlin/Native is native not for performance. It is for situations, where you can’t afford a JVM (like an iOS app) and want to share logic between platforms, or just write clean readable code. Kotlin/JVM is faster than K/N, and Rust is faster than both.

11 Likes

Why is Kotlin-Native slower than JVM? I thought LLVM was supposed to perform most of the optimisations independently of the front-end, but I suppose it could still rely on the front-end to some extent.

I think native is a better candidate for GObject bindings than JVM because it makes C-interop generally easier. Also native’s GC is based on reference-counting I believe? So is GObject’s, so although one would still be trying to use two different systems together, it could be a better fit because of RAII. GLib and its ecosystem also provide a wealth of utility libraries which can go a long way towards replacing what’s available for the JVM.

It is very hard to make something “faster” than JVM on the large projects with complicated structure because elaborate runtime optimization. So, yes, LLVM and Kotlin-Native are slower. With some exceptions:

  1. Program start will always be faster on K/N because it does not require class-loading and JIT.
  2. K/N will get not faster, but smoother performance due to GC pauses.
  3. Some operations could use intrinsics and super-optimization either by LLVM or K/N compiler itself. JVM has a lot of its own intrinsics, but those could be different.

Also you need to remember that it is almost impossible to write micro-programs on JVM, because the runtime itself is quite large.

My experience with rust was very bad

  1. tooling is garbage… working with rust with intellij is pain, vscode is not much better, every time i make a smallest change it will trigger cargo build under the hood and after 5-6 seconds idea will have info on what you changed

  2. it forces you to do things one way and one way only

  3. panic is idiotic idea, when did you last time thing that your program did the right thing by goind down just because some junior wrote some wrong function. Most programs are big services that respond to things last thing you want is for it to stop responding even if its stupid internal error… panic is ok for small tools you use in terminal like, you invoke them with a command and if you did something stupid it dies asap without doing anything else, you get non zero error code… thats not what we do in big software… this is like using bash to write a full http server with business logic… panic is idiotic idea

  4. its memory management forces you to clone structs all the time, its interesting idea and its the only thing that i find cool about rust, but its not worth it, forcing you to clone structs all the time making code less and less readable (not worth it)

  5. forces you to write huge functions if you need to work on piece of struct in one function and the rest on other function you either clone it for one or you put bunch of code in one big function… both are very bad, one is unnecessary memory copy other is garbage code. Also how often are you having memory leaks in java? its been 8 years since i had one, is it worth to cripple my code for that?

  6. there is nothing that rust does that you cant do with kotlin, you like to handle all your errors by passing it as response no one stops you from doing that, rust forces you to do it this way kotlin doesn’t but there are plenty of things i can do in kotlin that will look like garbage in rust… try to do something similar to coroutine state machines with rust you will write pages of garbage to do it…

  7. display and debug is idiotic idea again, your compilers job is not to babysit you so that you don’t accidentally log something sensitive in the logs, its your common sense and skill as a programmer, rust just gets on your way all the time, so they decided its a good idea to trade off intuitiveness of the language for some non problem…

overall imo its very overrated and its matter of time till people ditch it for go or rewrite in some other language, people go for it because of performance but its all about you writing smart performant code not the language… to me if your reason to use rust is performance then you are a bad programmer that doesn’t know how to do performance/latency and language is not going to fix it for you

my company tried rust cos spring apps were loading for a minute, instead of getting rid of spring they tried something else now we will probably end up rewriting this from scratch

its very opinionated language, authors decided for me how i’m supposed to write code and while that might be ok for noobs, its a huge negative for me, i want to have the option to use whatever i need to use, maybe i don’t want to return Option on every goddamn function…

also no one, NO ONE cares how fast your app starts, what matters is how fast it works when its warmed up and ready, there is nothing you can do in rust to be faster that cant be done on JVM

Regarding kotlin native i have tried it, its kotlin not much different from it but its definitely not ready for masses, however jetbrains knows how to do tooling i have no doubt that after short while working with native is going to be as easy as java/kotlin

6 Likes

I don’t know about Rust, so I can’t talk to most of those points.

But my experience regarding point 2 is clearly different from yours; in my experience, shutting down the whole program can be a very good response to some types of error.

Kotlin and Java distinguish Errors (which are generally unpredictable and unrecoverable) from Exceptions (which are generally predictable, and should be checked for and handled in an appropriate way). Here I’m thinking of the former — especially OutOfMemoryError, which can strike almost anywhere in your code, and which is almost impossible to recover from reliably.

If an application throws an Error, and you don’t catch it, that thread will die (and release any memory to which it had the only references). But other threads will continue. So the application will be in an unknown state (depending upon which thread died, and what it was doing).

Suppose you have a very simple application with only two threads: one reading data from an external source and pushing it onto a work queue, and another thread reading data from that queue and processing it somehow. If that first thread dies, then the second will process all the data remaining on the queue and then just sit there, doing nothing useful, for as long as it continues running. Unless you have very detailed external monitoring, that’s a situation you might not spot for quite some time — and meanwhile, the external data isn’t being read and could be lost for good. On the other hand, if the second thread dies, then work will just pile up on the queue, and so the application will run out of memory (again) before too long.

In either case, there’s no benefit, and lots of potential harm, from letting the application limp on. Far better for it to shut down completely, and let a launcher/supervisor (such as systemd or daemontools) restart it, to get it back to a known state.

(I’ve used a global UncaughtExceptionHandler to spot Errors and force the application to shut down — though that’s tricky to get right, especially if you want to log the error first, because anything you do could run out of memory again…)

Of course, most applications more complex than that, and so the consequences are less obvious. In some cases, the death of one thread might cause only limited damage and everything else could continue safely. But even applications that have many interchangeable short-running worker threads tend also have threads dedicated to monitoring or scheduling or listening to sockets or other activities whose death would cause trouble, whether catastrophic or subtle.

Also bear in mind that when the heap is almost full, the JVM garbage collector can get busy enough to really slow the application down, desperately trying to free up enough memory — so even if the thread ends up dying cleanly and the application continues, it could have acquired a huge backlog of work in the meantime — and unless that thread released a lot of memory, the other threads will also have to contend with a low-memory situation, so further failures are quite likely.

So continuing to run in such circumstances is almost always risky, and (depending on the broader context) forcing a shutdown can be the safest choice.

1 Like

Most applications are web services, one of the most used things with rust is tokio (that gives you good sense of what people try to do with the language), relatively new rust programmers can make mistake and use something that could panic(), or maybe something that can panic came in the library you use, which would kill your entire service… you don’t want that ever, individual requests can fail, having your entire service down is the worst.

Give me examples of actual usecase where you were glad for panic? rather than given an Err()…
I used this in JVM i had a custom WTF error (sands for what a terrible failure) which would trigger system.exit there were genuine uses of that that i thought ok this must never happen, if it does then i cant recover, after a while i realized its a stupid idea, i’d rather have my apps live and maybe retain some state that could tell me what was wrong.

regarding jvm, i do not remember in last 8 years to have issues with memory management or gc pauses… if you write common sense code that is correct logically you will not have any full heaps or long GCs… most amateur java programmers dont know what is a memory leak for many years until they somehow get one, its a rarity in jvm world. If you have problems with GCs or having a single millisecond latency is important for you there is Azure which has pausles GC… and there are tools that you can use to have no GC at all… this is why people write HFT applications in java more than they do in C or C++, in fact in my career i had 2 projects which were rewrites of such systems to java/kotlin.

Rust is like super interesting experiment, these days coming up with new languages is much easier than it seems, you do some moderate work slap LLVM and wow you now support all platforms imaginable, its the core ideas that matter, the memory ownership model is interesting but to me its a failed experiment, it gets in your way too much, it forces you to write code in specific ways that make it not worth it, performance is not a reason here… i did challenges with some rust programmers who thought rust is just fast for some magical reason, i wrote the same application in java and performance is on par sometimes even better than rust, because yes JIT is superior and 99% programmers cant write optimal code that jit will spit out after few compilations. Only advantage of performance of rust was statup time, which no one cares about.

2 Likes

0: i’m not sure what you mean i dont have this problem (did you tried with rust-analyzer?).
1: i don’t think so, rust allow a lot of pattern i’m not sure what you mean with this point.
2: panic is intended for unrecoverable errors if someone use it everywhere the problem is him not the language.
3: this is just the result of you didn’t know how to use (or understand) the rust ownership model nothing else, what you said it is even an anti pattern… Not abuse Clone.
4: did you hear about borrow? pass by reference? give ownership? (looks like you never learned rust properly)
5: of course kotlin is a high level language, rust not was designed to replace kotlin but C/C++. every language has it uses cases.
6: display and debug don’t harm anyone, this is not a compiler feature but a std lib feature…

people go for it because of performance but its all about you writing smart performant code

“people go for it because” it ownership model make easier to write this kind of code. rust is more hard to learn but easier to master than C that’s why rust exists.

i think your problem was using a low level programming language to build a web application is like you tried to build a web app with C, that don’t make sense at all, and rust is insanely faster than JVM Benchmarks (at least 10 times faster in most cases than JVM and about 2 times than KN also uses much less memory)

yes i tried rust analyzer its not like there are 15 alternatives, i both tried to use VSCode way and Intellij way of working with the language… and i remember how every single modification to a source file took seconds to show up in the tooling… maybe it improved but i doubt it, for it to actually improve compiler needs to cooperate via some sort of api.

regarding one way of doing things… how many ways can you do exception handling? concurrency?
maybe i do not want to return Results from every damn function maybe i’d rather throw an exception and catch it somewhere at the high level and keep my code clean and to the point…

yes panic is 100% your problem once you find out that the library you use can panic… what are you going to do then? you cant prevent it from panicing cant you? does that library developer think where his library will be used? i doubt that…

i never said display and debug are a compiler problem, i said its a stupid design and stupid idea, its baked in std lib which means you have to deal with it want it or not, its treating programmers like babies… if i want to log an object i must be able to do it period, no matter whats in it, its not the languages problem to solve… this is another example of language creator deciding for you how you should write code… rather than giving you a choice.

i no longer have my rust examples showing how ownership model comes at the cost of readability and maintainability of your code… i moved on from rust since creation of this post because i think this language while having some good ideas is faaaaaar cry from being ready for production use…

“rust is insanely faster than JVM” no its not, you should measure performance when your system is in optimal state to perform, JVM takes its sweet time to start and to optimize interpreted code… once it does its as fast as any of the low level languages… looking at the benchmark numbers from your link its obvious they have no clue what they are doing beyond basic timestamp measurement… anyone benchmarking jvm without JMH should not be taken seriously…

do you really believe it takes rust 40ms to do json benchmark while jvm 1800ms to do the same? maybe whoever is doing that benchmark has no idea what he is doing?

either way if you want to believe that, go for it, implement 1000s of lines of code in rust without doing proper research about actual performance… there is a reason people put 20 years of work into perfecting jvms… my prediction you’ll rewrite that code eventually or someone else will.

i’m developing trading systems and exchange systems which handle 10m+ requests per second (and its not the limit its just more than enough for us), i’m yet to see anyone do something similar in anything other than java, c or c++, we measure serialization in nanoseconds, it takes about 16 ns to serialize a message in my system. So anyone thinking down on jvm performance go check out OpenHFT project, check out Aeron and you’ll see that its not the language its your skill or garbage libraries like spring… or you can believe some random questionable benchmark that confirms your bias.

In the end none of it matters, if rust is so great it will overtake javascript and java…

3 Likes