Cache Rules Everything Around Me, and bloated executables generally put more stress on the instruction cache, resulting in poorer performance.
Of course, this is just an approximate general rule, and extremely small binaries (and generally any "pointless" experimentation) like this are mainly interesting from a learning point of view (or for small embedded microcontrollers), e.g. understanding syscalls and program start-up, and, for the write-up you link, the ELF format. (Not everything has to be inherently useful for an actual task.)
To play the advocate, given that by default compilation produces a binary that includes over 2KB of Lovecraft quotes¹, this article at least serves to reassure people that you can produce a compact binary with Rust.
It may matter in some embedded applications (for which chipsets there is not even Rust compiler support yet) but the point is to show off how much low-level control you have over code-generation, and that no run-time is needed.
I'd care a lot more about performance characteristics than binary size
The key word here is I'd. The programming world is vast, and the range of hardware is likewise vast. So, so vast. Really huge. Pick a restriction you don't have to worry about; someone else out there does.
These exercises may lack practical value, except perhaps to the virus makers, but they do kind of prove there is no extraneous overhead required by the language.
So we already knew that about assembler, now we also know Rust can be twisted quite close to that too.
Is there a process for making a fully static binary (say if I were to substitute an alternate libc, or provide my own low level wrappers for syscalls, or whatnot)?
I'd actually love to ask Linus' on his opinion of the practical uses of Rust in the Linux kernel. Does he think it could have a place, if not, why? Can those issues be addressed, etc?
Even if that means him dismissing me/my question entirely lol.
Rust seems very promising language , but why on earth should any one use rust in kernel development ? as far as I see this link is just calling write system call from rust program (which is very good) , but don't have anything to do with linus or kernel internal. and if you mean some thing like scripting in kernel ( i think openbsd ddne it with lua ) there is more viable and simpler choice than rust , like lua.
Because it allows (in some situations) dynamic memory allocation where the compiler can reason about when the memory becomes unused, thus guaranteeing that it's freed. In other words, you get to use algorithms which allocate off the heap without risking a memory leak. Plus a whole bunch of other useful features like Lisp-style structural macros, parametric polymorphism, compile time bounds checking, and other awesome stuff stolen from the functional programming world.
Yes, but the point was that it could be done in rust, using rust's language features (type safety and so forth). Making your main inline assembly isn't really using the language very much.
Even that is still type safe, just not portable. After all, every part of the memory is a collection of bytes (that is, a slice of u8) – whether you can access them is another story.
Wow. This is seriously impressive. Rust looks like it actually might be capable as a systems programming tool to match C. I have to learn more about it now! :)
If so I can see that working for very simple code, but what about wanting to use Tasks/Threads or do I/O. Is that converted to native system calls at compile time?
After a series of recent changes, Rust's runtime has been radically reduced. I/O goes through system calls, and the threading system is just native OS threads. There's a very small amount of support needed for the "Rust runtime", including things like stack guards, but it's much smaller than it was.
The RFC describing the changes is [^1] and the actual commit that finalized them is [^2].
> Now for comedy, someone find the size of a similar program in Go
As far as I know, Go statically links the runtime into the binary (including the garbage collector, the scheduling system and more)... so for a small program like this sample, it will appear to be abnormally bloated. If it were a larger, more complex example, then the binary size wouldn't change as drastically (and on a surface level might appear to be more justifiable).
It is also bad in following dependencies, and links the whole libraries. The result is like spaghetti, import on library and half of the standard libraries come with it. Some optimizations have been already done to prevent that, but the work is going to be still in progress for several versions.
On the other hand, rust has no standard library ("batteries") by explicit choice, so once the ecosystem will evolve, there would likely be multiple json or http libraries (just to name "low-level" libraries with widespread usage), and you might end up linking a few of them in a binary as indirect dependency.
> and you might end up linking a few of them in a binary as indirect dependency.
That's not a counter-argument to erglkjahlkh's comment. In fact it's pretty much irrelevant:
* Go works at a library level, when you import fmt you don't import encoding/json, and it's not loaded
* The issue he outlines is mostly that Go does little to no dead code elimination, when a library is imported all of its content (and the content of its dependencies) will end up in the final library, even if you only access a small utility function
Sadly no: one of the primary (if not the primary) goal of Go's developers is compilation speed, and with Go being intrinsically slower than C the post-rewrite available budget for possible optimisations (whatever the acceptance threshold they define) will be lower rather than higher.
Rust produces statically linked binaries by default, while GCC and Clang default to dynamic linking. For a better comparison, pass `-static` to GCC/Clang, or pass `-C prefer-dynamic` to rustc.
Ah of course, thanks! That makes sense. Since I'm on OSX and -static doesn't work with GCC (libs provided aren't static) - I'll believe it instead. Rustc is now 9K, which is really close to 8.7 of GCC.
Is it possible to make actual static binaries in rust? By default it compiles in the rust libraries, but depends on glibc and friends (and is not actually a static binary) -- at least with tip of tree rust from yesterday.
You can drop the glibc dependency pretty easily. One way (used for a lot of toy kernels that have been written in Rust) is to add the #![no_std] attribute and then explicitly pull in any static dependencies you still use (like libcore).
But honestly... does it really matter how small your executable is? I'd care a lot more about performance characteristics than binary size.
[1] http://www.muppetlabs.com/~breadbox/software/tiny/teensy.htm...