Open tekjar opened 9 years ago
Any tips about dynamic linking ?
You can pass -C prefer-dynamic
to rustc
to get a dynamically linked binary.
$ rustc -C prefer-dynamic hello.rs
$ ls -lh hello
-rwxr-xr-x 1 japaric japaric 8.5K hello
But it's not working for me when cross compiling - I'm getting some errors due to missing unwind symbols at link time. Will have to investigate.
Do note that the produced binary will be dynamically linked to the std
crate, so you'll have to keep a copy of rustlib/mips-unknown-linux-gnu/lib/libstd-deadbeef.so
, which is ~4.8 MB (!), in your router.
Size of hello world is about 650kb.
You can bring it down a bit further with -C lto -O
, I get 458K
.
FWIW, I recompiled the std
crate without jemalloc support and that shrank the size of a hello world binary to 230K. It might be worthwhile to investigate having the std
dynamically linked to jemalloc, that would make each rust binary ~200K smaller at the cost of having to install libjemalloc.so (which I guess should be ~400K in size) library in the target device.
You mean, std
crate would be statically linked to every rust binary while dynamically linking to jemalloc
?
Yes, by default jemalloc is statically linked to the std crate, so every rust binary that depends on the std crate will have a copy of jemalloc in it. If instead we build a std that's dynamically linked to jemalloc, then each rust binary would also be dynamically linked to jemalloc and would become ~200K smaller.
:+1: That is a great idea. Binary size is preventing me to start any serious work on openwrt with Rust. This will help a lot. Please keep us posted if you have more optimizations :)
if you have more optimizations
There are other C libraries like libcompiler-rt, libbacktrace, librustrt_native, etc that are statically linked to the std crate, changing their linkage from static to dynamic should make the binary size even smaller.
Please keep us posted
Right now I'm working on cross compiling the std crate using cargo, which I got mostly working. Now I want to add cargo features that will let you control what gets statically/dynamically linked to the std crate. I'll publish this as soon as I get something reproducible and relatively easy to use.
Update: I made backtrace [1] optional via a cargo feature, and with backtrace disabled the size of hello world is 97K.
[1] I mean the stack backtrace that you get when your program panics and the RUST_BACKTRACE variable is set.
This is with jemalloc
being compiled statically? 650K to 97K is huge. But debugging might be difficult during panics.
This is with jemalloc being compiled statically?
No, this is without jemalloc, i.e. using libc malloc. I have yet to add a cargo feature to enable jemalloc.
But debugging might be difficult during panics.
Since backtrace is a cargo feature, you could enable it during development and disable it for release.
-C opt-level=3 -C lto -C link-args=-s
With these options, size has come down to 312K. But compilation is taking little longer.
With these options, size has come down to 312K
Nice wins. I tested adding the -s
flag to my previous changes and the binary size went down from 97KB to 73KB.
FYI, I've added a section to the README about making binaries smaller, and I have also published my work on cross compiling the std
crate using cargo here.
But compilation is taking little longer.
Yes, LTO greatly increases build time. I'd recommend disabling it during development and enabling it for release.
I'll be working on enabling jemalloc via a cargo feature now.
Update: I've now implemented a cargo feature that lets you dynamically link every Rust program to jemalloc.
With these changes the 73KB hello world without jemalloc support went up to 77KB but now it uses jemalloc. To use this binary, libjemalloc.so.2 needs to be installed in the target device. The unstripped version of libjemalloc.so.2 is 351KB, and stripping it with strip --strip-all
brings its size down to 271KB.
-Z no-landing-pads
. This is helping a little to further bring down the size
cargo rustc --target=mips-unknown-linux-gnu --release -- -C link-args=-s -C no-stack-check -Z no-landing-pads
-rwxrwxr-x 1 ravitejareddy ravitejareddy 61764 Jun 23 00:53 hello
This is with dynamic jemalloc and backtrace disabled
Size of hello world is about 650kb. Flash size of my router is about 8MB. Static linking might not be the right option if I want to flash multiple binaries. Any tips about dynamic linking ?