8 ms·
151-byte static Linux binary in Rust
- userbinator 12y agoThat main() can still be improved... try this: push 1 pop eax mov edi, eax mov esi, 400008h push 7 pop edx syscall push 3ch pop eax xor edi, edi syscall It should be 10 bytes shorter.
- ekimekim 12y agoYes, 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.
- omega_rythm 12y agoYou really should have a look at the rust code this guy wrote. I would not call that last optimization type safe.
- the_mitsuhiko 12y agoHow so? The only unsafe part is the transmute which only saves 7 bytes anyways :P
- exprL 12y agoEven 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.
- userbinator 12y agoFrom the Github page: https://github.com/kmcallister/tiny-rust-demo https://github.com/kmcallister/tiny-rust-demo All of the machine code comes out of rustc. (Although all of the instructions that survive optimization went in as inline assembly.) So while his main() is written in (unsafe) Rust, he's basically using it as a macroassembler.
- taralx 12y agoLLVM currently does not optimize for size, so things like the small-integer push/pop trick aren't goign to happen.
- RandomCode 12y agoI can go a lot lower. Silly contest. The people at OSDev think it's good if it can run on a 386. Mine is modern and requires a 64-Bit 2 Ghz CPU.
- tdicola 12y agoThat is really impressive. Now for comedy, someone find the size of a similar program in Go.
- Alupis 12y ago> 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).
- erglkjahlkh 12y agoIt 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.
- giovannibajo1 12y agoOn 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.
- masklinn 12y ago> On the other hand, rust has no standard library ? http://doc.rust-lang.org/std/ http://doc.rust-lang.org/std/ > there would likely be multiple json or http libraries (just to name "low-level" libraries with widespread usage) The standard library used to build json in, that was actually split out to a standalone libraries for various reasons: https://github.com/rust-lang/rustc-serialize https://github.com/rust-lang/rustc-serialize > 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
- Alupis 12y agoreminds me a bit of the "Creating Really Teensy ELF Executables" writeup[1], which got down to 45 bytes. 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.html http://www.muppetlabs.com/~breadbox/software/tiny/teensy.htm...
- jeremyjh 12y agoIt 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.
- dbaupp 12y agoCache 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.)
- semi-extrinsic 12y agoI'm going to have to steal your opening quote, for times when I have to keep it real*8. Source?
- dbaupp 12y agoNo idea where I first heard it; I have a feeling it was on IRC from the author of the article, coincidentally.
- jarfil 12y agoThese 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.
- starmole 12y agoWow. 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! :)
- 0xFFC 12y agodude its great , but not that good, at least not yet .
- zxcdw 12y agoCare to elaborate why do you think so?
- berkut 12y agoWell for one: at least currently, there's a much better chance of having the c/c++ runtimes on a system than the Rust one I imagine.
- cpach 12y agoAFAIK you can compile static binaries with Go and thus eliminate the dependencies.
- cpach 12y agoOops, apparently I was a little fast there. Apologies! (Edit: I mistook this for a Go thread.)
- steveklabnik 12y agoYou don't need a Rust runtime installed, you just need a glibc.
- berkut 12y agoEven if you don't statically link Rust's runtime? 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?
- yazaddaruvala 12y agoI'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.
- 0xFFC 12y agoRust 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.
- jnbiche 12y ago> but why on earth should any one use rust in kernel development Because that's explicitly one of the things Rust was developed for. Here's a whole list of kernels and other OS projects that have been created using Rust: https://github.com/rust-lang/rust/wiki/Operating-system-development https://github.com/rust-lang/rust/wiki/Operating-system-deve...
- david-given 12y agoBecause 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.
- hga 12y agoI gather LLVM has too few backends, and fewer quality ones, to be suitable for such a general purpose OS. As I recall Rust is currently targeting only Intel and ARM backends. And it's way too early to see if it'll make it.
- CyberShadow 12y agoI did something similar in D/Win32: http://forum.dlang.org/post/qcbicxrtmjmwiljsyhdf@forum.dlang.org http://forum.dlang.org/post/qcbicxrtmjmwiljsyhdf@forum.dlang... The PE format is rather bulkier than ELF, though.
- Keyframe 12y agoI just had a look. Installed nightly Rust on OSX and ran through it a hello world program - 307K! HW in C with gcc 4.2.1 (LLVM) makes 8.7K.
- epdtry 12y agoRust 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. On Linux, with dynamic linking: rustc: 8656 bytes clang: 6960 bytes gcc: 6688 bytes
- Keyframe 12y agoAh 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.
- swetland 12y agoIs 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.
- Rusky 12y agoYou 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).
- swetland 12y agoThis is cute, but is there a way to actually create static binaries with the standard tooling and not jumping through hoops? Hello World in Rust with tip of tree (as of yesterday) is a ~500K binary that depends on glibc and friends. Switching from println!() to std::io...write_str() actually made it larger!
- steveklabnik 12y agoYou can't static link glibc, so our static binaries still have a dynamic dependency on it.
- cowsandmilk 12y agoand for many, there are legal issues with statically linking glibc due to its license.
- swetland 12y agoIs 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)?
- steveklabnik 12y agoYes, that's totally possible. You can write a kernel in Rust if you want.
- tdrd 12y ago...is it documented anywhere? where?
- steveklabnik 12y agohttp://doc.rust-lang.org/book/unsafe.html#avoiding-the-standard-library http://doc.rust-lang.org/book/unsafe.html#avoiding-the-stand... is the closest we have, currently. https://github.com/rust-lang/rust/wiki/Operating-system-development https://github.com/rust-lang/rust/wiki/Operating-system-deve... has a bunch of stuff, and https://github.com/charliesome/rustboot https://github.com/charliesome/rustboot and its forks are examples that I know of.