Po znalezieniu Rusta i przeczytaniu dwóch pierwszych rozdziałów dokumentacji uważam, że podejście i sposób, w jaki zdefiniowali język, są szczególnie interesujące. Postanowiłem więc zmoczyć palce i zacząłem od Hello world ...
Zrobiłem to na Windows 7 x64, przy okazji.
fn main() {
println!("Hello, world!");
}
Wydając cargo build
i patrząc na wynik w targets\debug
, znalazłem wynikowy .exe
3 MB. Po kilku poszukiwaniach (dokumentacja flag linii poleceń cargo jest trudna do znalezienia ...) znalazłem --release
opcję i stworzyłem kompilację wydania. Ku mojemu zdziwieniu rozmiar .exe zmniejszył się tylko nieznacznie: 2,99 MB zamiast 3 MB.
Tak więc, wyznając, że jestem nowicjuszem w Rusta i jego ekosystemie, spodziewałem się, że język programowania systemów stworzy coś zwartego.
Czy ktoś może wyjaśnić, do czego Rust kompiluje się, jak to możliwe, że tworzy tak ogromne obrazy z programu 3-liniowego? Czy kompiluje się do maszyny wirtualnej? Czy istnieje polecenie strip, które przegapiłem (informacje o debugowaniu w kompilacji wydania?)? Coś jeszcze, co mogłoby pozwolić zrozumieć, co się dzieje?
źródło
Odpowiedzi:
Rust używa statycznego linkowania do kompilowania swoich programów, co oznacza, że wszystkie biblioteki wymagane przez nawet najprostszy
Hello world!
program zostaną wkompilowane w plik wykonywalny. Obejmuje to również środowisko wykonawcze Rust.Aby zmusić Rusta do dynamicznego łączenia programów, użyj argumentów wiersza poleceń
-C prefer-dynamic
; spowoduje to znacznie mniejszy rozmiar pliku, ale będzie również wymagać, aby biblioteki Rust (w tym jego środowisko wykonawcze) były dostępne dla programu w czasie wykonywania. Zasadniczo oznacza to, że będziesz musiał je podać, jeśli komputer ich nie ma, zajmując więcej miejsca niż zajmuje oryginalny statycznie połączony program.Ze względu na przenośność zalecałbym statyczne połączenie bibliotek Rust i środowiska uruchomieniowego w sposób, w jaki miałbyś kiedykolwiek rozprowadzać swoje programy wśród innych.
źródło
cargo rustc [--debug or --release] -- -C prefer-dynamic
Nie mam żadnych systemów Windows do wypróbowania, ale w Linuksie statycznie skompilowany świat Rust hello jest w rzeczywistości mniejszy niż odpowiednik C.Jeśli widzisz ogromną różnicę w rozmiarze, prawdopodobnie dzieje się tak dlatego, że łączysz plik wykonywalny Rusta statycznie, a C dynamicznie.
W przypadku łączenia dynamicznego należy wziąć pod uwagę rozmiar wszystkich bibliotek dynamicznych, a nie tylko plików wykonywalnych.
Tak więc, jeśli chcesz porównać jabłka z jabłkami, upewnij się, że oba są dynamiczne lub oba są statyczne. Różne kompilatory będą miały różne wartości domyślne, więc nie możesz po prostu polegać na domyślnych ustawieniach kompilatora, aby uzyskać ten sam wynik.
Jeśli jesteś zainteresowany, oto moje wyniki:
Zostały one skompilowane za pomocą gcc (Debian 4.9.2-10) 4.9.2 i rustc 1.0.0-nightly (d17d6e7f1 2015-04-02) (zbudowany 2015-04-03), zarówno z domyślnymi opcjami, jak i
-static
dla gcc i-C prefer-dynamic
dla rustc.Miałem dwie wersje świata C hello, ponieważ pomyślałem, że użycie
puts()
może łączyć się w mniejszej liczbie jednostek kompilacji.Jeśli chcesz spróbować odtworzyć go w systemie Windows, oto źródła, z których korzystałem:
printf.c:
puts.c:
rust.rs
Należy również pamiętać, że różne ilości informacji debugowania lub różne poziomy optymalizacji również miałyby znaczenie. Ale spodziewam się, że jeśli widzisz ogromną różnicę, jest to spowodowane łączeniem statycznym i dynamicznym.
źródło
strip -s
, spada z 1,6M do 190K. Powstawanie uwalnianiu (domyślnych orazopt-level='s'
,lto = true
orazpanic = 'abort'
w celu zminimalizowania wielkości) spada od 623K do 158k.Podczas kompilacji z Cargo możesz użyć dynamicznego łączenia:
Spowoduje to radykalne zmniejszenie rozmiaru pliku binarnego, ponieważ jest on teraz dynamicznie połączony.
Przynajmniej w Linuksie możesz również usunąć plik binarny symboli za pomocą
strip
polecenia:Spowoduje to zmniejszenie o około połowę rozmiaru większości plików binarnych.
źródło
Przegląd wszystkich sposobów zmniejszania rozmiaru pliku binarnego Rusta można znaleźć w
min-sized-rust
repozytorium.Obecne kroki mające na celu zmniejszenie rozmiaru plików binarnych to:
jemalloc
domyślnie)Cargo.toml
cargo build --release
strip
wynikowy plik binarny.Za pomocą
nightly
Rusta można zrobić więcej , ale zostawię tę informację,min-sized-rust
ponieważ zmienia się ona w czasie z powodu użycia niestabilnych funkcji.Możesz także użyć
#![no_std]
do usunięcia Rdzylibstd
. Zobaczmin-sized-rust
szczegóły.źródło
To jest funkcja, a nie błąd!
Możesz określić wersje biblioteki (w powiązanym z projektem pliku Cargo.toml ) używanej w programie (nawet te niejawne), aby zapewnić zgodność wersji biblioteki. To z drugiej strony wymaga, aby określona biblioteka była statycznie połączona z plikiem wykonywalnym, generując duże obrazy w czasie wykonywania.
Hej, to już nie 1978 - wiele osób ma więcej niż 2 MB RAM w swoich komputerach :-)
źródło