Ayant juste trouvé Rust et ayant lu les deux premiers chapitres de la documentation, je trouve l'approche et la façon dont ils ont défini le langage particulièrement intéressantes. J'ai donc décidé de me mouiller les doigts et j'ai commencé avec Hello world ...
Je l'ai fait sur Windows 7 x64, btw.
fn main() {
println!("Hello, world!");
}
En émettant cargo build
et en regardant le résultat, targets\debug
j'ai trouvé que le résultat .exe
était 3MB. Après quelques recherches (la documentation des drapeaux de la ligne de commande de fret est difficile à trouver ...), j'ai trouvé l' --release
option et créé la version de version. À ma grande surprise, la taille du .exe n'est devenue plus petite que d'un montant insignifiant: 2,99 Mo au lieu de 3 Mo.
Donc, en admettant que je suis un débutant dans Rust et son écosystème, je m'attendais à ce qu'un langage de programmation système produise quelque chose de compact.
Quelqu'un peut-il expliquer ce que Rust compile, comment il peut être possible de produire des images aussi énormes à partir d'un programme 3 lignes? S'agit-il d'une compilation sur une machine virtuelle? Y a-t-il une commande de bande que j'ai manquée (informations de débogage dans la version de version?)? Y a-t-il autre chose qui pourrait permettre de comprendre ce qui se passe?
la source
Réponses:
Rust utilise des liens statiques pour compiler ses programmes, ce qui signifie que toutes les bibliothèques requises par le
Hello world!
programme le plus simple seront compilées dans votre exécutable. Cela inclut également le runtime Rust.Pour forcer Rust à lier dynamiquement des programmes, utilisez les arguments de ligne de commande
-C prefer-dynamic
; cela se traduira par une taille de fichier beaucoup plus petite mais exigera également que les bibliothèques Rust (y compris son exécution) soient disponibles pour votre programme au moment de l'exécution. Cela signifie essentiellement que vous devrez les fournir si l'ordinateur ne les a pas, occupant plus d' espace que votre programme d'origine lié statiquement.Pour la portabilité, je vous recommande de lier statiquement les bibliothèques Rust et le runtime comme vous l'avez fait si vous deviez jamais distribuer vos programmes à d'autres.
la source
cargo rustc [--debug or --release] -- -C prefer-dynamic
Je n'ai pas de système Windows à essayer, mais sous Linux, un monde Rust hello compilé statiquement est en fait plus petit que l'équivalent C.Si vous voyez une énorme différence de taille, c'est probablement parce que vous liez l'exécutable Rust statiquement et le C dynamiquement.
Avec la liaison dynamique, vous devez également prendre en compte la taille de toutes les bibliothèques dynamiques, pas seulement l'exécutable.
Donc, si vous souhaitez comparer des pommes avec des pommes, vous devez vous assurer que les deux sont dynamiques ou les deux sont statiques. Différents compilateurs auront des valeurs par défaut différentes, vous ne pouvez donc pas vous fier uniquement aux valeurs par défaut du compilateur pour produire le même résultat.
Si vous êtes intéressé, voici mes résultats:
Ceux-ci ont été compilés avec gcc (Debian 4.9.2-10) 4.9.2 et rustc 1.0.0-nightly (d17d6e7f1 2015-04-02) (construit 2015-04-03), à la fois avec les options par défaut et avec
-static
pour gcc et-C prefer-dynamic
pour rustc.J'avais deux versions du monde C hello parce que je pensais que l'utilisation
puts()
pouvait être liée à moins d'unités de compilation.Si vous souhaitez essayer de le reproduire sous Windows, voici les sources que j'ai utilisées:
printf.c:
met.c:
rouille.rs
Gardez également à l'esprit que différentes quantités d'informations de débogage ou différents niveaux d'optimisation feraient également une différence. Mais je suppose que si vous voyez une énorme différence, c'est dû à la liaison statique par rapport à la liaison dynamique.
la source
strip -s
, passe de 1,6M à 190K. La version de version (valeurs par défaut plusopt-level='s'
,lto = true
etpanic = 'abort'
pour réduire la taille) passe de 623 Ko à 158 Ko.Lors de la compilation avec Cargo, vous pouvez utiliser la liaison dynamique:
Cela réduira considérablement la taille du binaire, car il est maintenant lié dynamiquement.
Sur Linux, au moins, vous pouvez également supprimer le binaire des symboles à l'aide de la
strip
commande:Cela réduira environ de moitié la taille de la plupart des binaires.
la source
Pour un aperçu de toutes les façons de réduire la taille d'un binaire Rust, consultez le
min-sized-rust
référentiel.Les étapes de haut niveau actuelles pour réduire la taille binaire sont:
jemalloc
par défaut)Cargo.toml
cargo build --release
strip
sur le binaire résultant.Il y a plus à faire avec
nightly
Rust, mais je laisserai ces informationsmin-sized-rust
car elles changent avec le temps en raison de l'utilisation de fonctionnalités instables.Vous pouvez également utiliser
#![no_std]
pour supprimer Rustlibstd
. Voirmin-sized-rust
pour plus de détails.la source
C'est une fonctionnalité, pas un bug!
Vous pouvez spécifier les versions de bibliothèque (dans le fichier Cargo.toml associé au projet ) utilisées dans le programme (même les versions implicites) pour assurer la compatibilité des versions de bibliothèque. Ceci, d'autre part, nécessite que la bibliothèque spécifique soit liée statiquement à l'exécutable, générant de grandes images d'exécution.
Hé, ce n'est plus 1978 - beaucoup de gens ont plus de 2 Mo de RAM dans leurs ordinateurs :-)
la source