japaric-archived / rust-on-openwrt

[SUPERSEDED] by https://github.com/japaric/rust-cross
82 stars 5 forks source link

This is a great start but size of the binary is too big due to static linking. Dynamic linking ?? #1

Open tekjar opened 9 years ago

tekjar commented 9 years ago

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 ?

japaric commented 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.

japaric commented 9 years ago

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.

tekjar commented 9 years ago

You mean, std crate would be statically linked to every rust binary while dynamically linking to jemalloc ?

japaric commented 9 years ago

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.

tekjar commented 9 years ago

:+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 :)

japaric commented 9 years ago

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.

japaric commented 9 years ago

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.

tekjar commented 9 years ago

This is with jemalloc being compiled statically? 650K to 97K is huge. But debugging might be difficult during panics.

japaric commented 9 years ago

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.

tekjar commented 9 years ago

-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.

japaric commented 9 years ago

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.

japaric commented 9 years ago

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.

tekjar commented 9 years ago

-Z no-landing-pads . This is helping a little to further bring down the size

tekjar commented 9 years ago

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