Nachdem ich Rust gefunden und die ersten beiden Kapitel der Dokumentation gelesen habe, finde ich den Ansatz und die Art und Weise, wie sie die Sprache definiert haben, besonders interessant. Also beschloss ich, meine Finger nass zu machen und begann mit Hello World ...
Ich habe das übrigens unter Windows 7 x64 gemacht.
fn main() {
println!("Hello, world!");
}
Als ich cargo build
das Ergebnis herausgab und betrachtete, stellte targets\debug
ich fest, dass das Ergebnis .exe
3 MB betrug. Nach einigem Suchen (Dokumentation der Frachtbefehlszeilenflags ist schwer zu finden ...) habe ich die --release
Option gefunden und den Release-Build erstellt. Zu meiner Überraschung ist die EXE-Größe nur unwesentlich kleiner geworden: 2,99 MB statt 3 MB.
Als ich gestand, dass ich ein Neuling in Rust und seinem Ökosystem bin, hätte ich erwartet, dass eine Systemprogrammiersprache etwas Kompaktes hervorbringen würde.
Kann jemand näher erläutern, woraus Rust kompiliert und wie es möglich sein kann, dass aus einem 3-Liner-Programm so große Bilder erzeugt werden? Wird es zu einer virtuellen Maschine kompiliert? Gibt es einen Strip-Befehl, den ich verpasst habe (Debug-Informationen im Release-Build?)? Gibt es noch etwas, das es erlauben könnte zu verstehen, was los ist?
quelle
Antworten:
Rust verwendet statische Verknüpfungen, um seine Programme zu kompilieren. Dies bedeutet, dass alle Bibliotheken, die selbst das einfachste
Hello world!
Programm benötigt , in Ihre ausführbare Datei kompiliert werden. Dies schließt auch die Rust-Laufzeit ein.Verwenden Sie die Befehlszeilenargumente, um Rust zu zwingen, Programme dynamisch zu verknüpfen
-C prefer-dynamic
. Dies führt zu einer viel kleineren Dateigröße , erfordert jedoch auch, dass die Rust-Bibliotheken (einschließlich ihrer Laufzeit) zur Laufzeit für Ihr Programm verfügbar sind. Dies bedeutet im Wesentlichen, dass Sie sie bereitstellen müssen, wenn der Computer sie nicht hat, was mehr Speicherplatz beansprucht, als Ihr ursprüngliches statisch verknüpftes Programm beansprucht.Aus Gründen der Portabilität würde ich empfehlen, die Rust-Bibliotheken und die Laufzeit statisch so zu verknüpfen, wie Sie es getan haben, wenn Sie Ihre Programme jemals an andere verteilen würden.
quelle
cargo rustc [--debug or --release] -- -C prefer-dynamic
Ich habe keine Windows-Systeme zum Anprobieren, aber unter Linux ist eine statisch kompilierte Rust-Hallo-Welt tatsächlich kleiner als das entsprechende C. Wenn Sie einen großen Größenunterschied feststellen, liegt dies wahrscheinlich daran, dass Sie die ausführbare Rust-Datei verknüpfen statisch und das C dynamisch.
Bei der dynamischen Verknüpfung müssen Sie auch die Größe aller dynamischen Bibliotheken berücksichtigen, nicht nur die ausführbare Datei.
Wenn Sie also Äpfel mit Äpfeln vergleichen möchten, müssen Sie sicherstellen, dass entweder beide dynamisch oder beide statisch sind. Unterschiedliche Compiler haben unterschiedliche Standardeinstellungen, sodass Sie sich nicht einfach auf die Compiler-Standardeinstellungen verlassen können, um das gleiche Ergebnis zu erzielen.
Wenn Sie interessiert sind, hier sind meine Ergebnisse:
Diese wurden mit gcc (Debian 4.9.2-10) 4.9.2 und rustc 1.0.0-nightly (d17d6e7f1 2015-04-02) (erstellt am 03.04.2015) kompiliert, sowohl mit Standardoptionen als auch mit
-static
für gcc und-C prefer-dynamic
für rustc.Ich hatte zwei Versionen der C-Hallo-Welt, weil ich dachte, die Verwendung
puts()
könnte weniger Kompilierungseinheiten enthalten.Wenn Sie versuchen möchten, es unter Windows zu reproduzieren, habe ich folgende Quellen verwendet:
printf.c:
puts.c:
rust.rs
Beachten Sie auch, dass unterschiedliche Mengen an Debugging-Informationen oder unterschiedliche Optimierungsstufen ebenfalls einen Unterschied machen würden. Aber ich gehe davon aus, dass ein großer Unterschied auf statische und dynamische Verknüpfungen zurückzuführen ist.
quelle
strip -s
, sinkt von 1,6 Millionen auf 190 KB. Der Release - Build (Standard Plusopt-level='s'
,lto = true
undpanic = 'abort'
Größe zu minimieren) fällt von 623K bis 158K.Beim Kompilieren mit Cargo können Sie dynamische Verknüpfungen verwenden:
Dadurch wird die Größe der Binärdatei drastisch reduziert, da sie jetzt dynamisch verknüpft ist.
Zumindest unter Linux können Sie die Binärdatei der Symbole auch mit dem folgenden
strip
Befehl entfernen:Dadurch wird die Größe der meisten Binärdateien ungefähr halbiert.
quelle
Eine Übersicht über alle Möglichkeiten zum Reduzieren der Größe einer Rust-Binärdatei finden Sie im
min-sized-rust
Repository.Die aktuellen Schritte auf hoher Ebene zur Reduzierung der Binärgröße sind:
jemalloc
standardmäßig nicht enthalten ).Cargo.toml
cargo build --release
strip
die resultierende Binärdatei aus.Mit
nightly
Rust kann noch mehr getan werden , aber ich werde diese Informationen belassen,min-sized-rust
da sie sich im Laufe der Zeit aufgrund der Verwendung instabiler Funktionen ändern.Sie können auch
#![no_std]
Rusts entfernenlibstd
. Siehemin-sized-rust
für Details.quelle
Dies ist eine Funktion, kein Fehler!
Sie können die im Programm verwendeten Bibliotheksversionen (in der dem Projekt zugeordneten Datei Cargo.toml ) angeben (auch die impliziten), um die Kompatibilität der Bibliotheksversionen sicherzustellen. Dies erfordert andererseits, dass die spezifische Bibliothek statisch mit der ausführbaren Datei verknüpft ist, wodurch große Laufzeitbilder erzeugt werden.
Hey, es ist nicht mehr 1978 - viele Leute haben mehr als 2 MB RAM in ihren Computern :-)
quelle