Rust çalıştırılabilir dosyaları neden bu kadar büyük?


153

Rust'u bulduktan ve belgelerin ilk iki bölümünü okuduktan sonra, yaklaşımı ve dili tanımlama şekillerini özellikle ilginç buluyorum. Bu yüzden parmaklarımı ıslatmaya karar verdim ve Merhaba dünya ile başladım ...

Bunu Windows 7 x64, btw'de yaptım.

fn main() {
    println!("Hello, world!");
}

Sonucu yayınlamak cargo buildve sonuca bakmaktargets\debug I sonuçlanan bulundu .exeolmanın 3MB. Bazı aramalardan sonra (kargo komut satırı bayraklarının belgelenmesi zor ...) --releaseSeçenek buldum ve serbest bırakma derlemesini oluşturdum. Şaşırtıcı bir şekilde, .exe boyutu sadece önemsiz bir miktarda küçüldü: 3MB yerine 2.99MB.

Bu yüzden, Rust ve ekosistemine yeni başlamış olduğumu itiraf ederek, bir Sistem Programlama dilinin kompakt bir şey üreteceği beklentim olurdu.

Rust'un neyi derlediğini, 3 katlı bir programdan bu kadar büyük görüntüler üretmenin nasıl mümkün olabileceğini herkes anlatabilir mi? Sanal bir makineye mi derleniyor? Kaçırdığım bir şerit komutu var mı (sürüm derlemesinde bilgi hata ayıklama?)? Neler olup bittiğini anlayabilecek başka bir şey var mı?


4
3Mb'nin sadece Hello World'ü değil, platform için gerekli tüm ortamı da içerdiğini düşünüyorum. Aynı şey Qt. Bu, 6 satırlı bir program yazarsanız, boyutun 6 Mb olacağı anlamına gelmez. 3Mb'de kalacak ve bundan sonra çok yavaş büyüyecek.
Andrei Nikolaenko

8
@AndreiNikolaenko Bunun farkındayım. Ancak bu, kitaplıkları C'nin yaptığı gibi ele almadıklarını, yalnızca bir görüntüye gerekenleri eklediğini veya başka bir şeyin devam ettiğini ima ediyor.
BitTickler

@ user2225104 Cevabımı gör, RUST kütüphaneleri C ile aynı (veya benzer) şekilde işler, ancak varsayılan olarak C statik kütüphaneleri programınıza derlemez (en azından C ++ ile).
AStopher


1
Bu şimdi eskimiş mi? Rustc sürüm 1.35.0 ve hiçbir cli seçeneği ile 137kb boyutunda bir exe olsun. Şimdi otomatik olarak dinamik olarak bağlı olarak derleniyor mu veya bu arada başka bir şey oldu mu?
itmuckel

Yanıtlar:


139

Rust, programlarını derlemek için statik bağlantı kullanır, yani en basit Hello world!programın gerektirdiği tüm kütüphaneler yürütülebilir dosyalarınıza derlenecektir. Bu, Rust çalışma zamanını da içerir.

Rust'u programları dinamik olarak bağlamaya zorlamak için komut satırı bağımsız değişkenlerini kullanın -C prefer-dynamic; bu çok daha küçük bir dosya boyutuyla sonuçlanır, ancak Rust kütüphanelerinin (çalışma zamanı dahil) çalışma zamanında programınız için de kullanılabilir olmasını gerektirir. Bu aslında bilgisayarda yoksa, statik olarak bağlanmış orijinal programınızdan daha fazla yer kaplamanız gerekir.

Taşınabilirlik için, Rust kütüphanelerini ve çalışma zamanını, programlarınızı başkalarına dağıtmak için yaptığınız şekilde statik olarak bağlamanızı tavsiye ederim.


4
@ user2225104 Kargo'dan emin değilsiniz, ancak GitHub'daki bu hata raporuna göre , bu ne yazık ki henüz mümkün değil.
AStopher

2
Ancak, bir sistemde 2'den fazla pas yürütülebiliri olduğunda, dinamik bağlantı size yerden tasarruf etmeye başlayacaktır…
binki

15
Statik bağlamanın devasa HELLO-WORLD'ü açıkladığını sanmıyorum. Sadece kütüphanelerin gerçekten kullanılan bölümlerine bağlanmamalı ve HELLO-WORLD neredeyse hiçbir şey kullanmıyor mu?
MaxB

8
BitTicklercargo rustc [--debug or --release] -- -C prefer-dynamic
Zach Mertes

3
@daboross Çok teşekkür ederim. Bu ilgili RFC'yi izliyorum . Rust, sistem programlamayı da hedeflediği için gerçekten üzücü.
Franklin Yu

62

Denemek için herhangi bir Windows sistemim yok, ancak Linux'ta, statik olarak derlenmiş bir Rust merhaba dünyası aslında eşdeğer C'den daha küçük. statik ve C dinamik olarak.

Dinamik bağlantı ile, yalnızca yürütülebilir kitaplıkları değil, tüm dinamik kitaplıkların boyutunu da dikkate almanız gerekir.

Bu nedenle, elmaları elmalarla karşılaştırmak istiyorsanız, her ikisinin de dinamik olduğundan veya her ikisinin de statik olduğundan emin olmanız gerekir. Farklı derleyiciler farklı varsayılanlara sahip olacaktır, bu nedenle aynı sonucu üretmek için derleyici varsayılanlarına güvenemezsiniz.

İlgileniyorsanız, sonuçlarım:

-rw-r - r-- 1 aij aij 63 Nis 5 14:26 printf.c
-rwxr-xr-x 1 aij aij 6696 5 Nisan 14:27 printf.dyn
-rwxr-xr-x 1 aij aij 829344 5 Nisan 14:27 printf.static
-rw-r - r-- 1 aij aij 59 Nis 5 14:26 koyar.
-rwxr-xr-x 1 aij aij 6696 5 Nisan 14:27 puts.dyn
-rwxr-xr-x 1 aij aij 829344 5 Nisan 14:27 puts.static
-rwxr-xr-x 1 aij aij 8712 Nis 5 14:28 rust.dyn
-rw-r - r-- 1 aij aij 46 Nis 5 14:09 rust.rs
-rwxr-xr-x 1 aij aij 661496 5 Nisan 14:28 rust.static

Bunlar, hem varsayılan seçeneklerle hem de -staticgcc ve -C prefer-dynamiciçin gcc (Debian 4.9.2-10) 4.9.2 ve rustc 1.0.0-nightly (d17d6e7f1 2015-04-02) (2015-04-03 ile oluşturulmuş) ile derlendi rustc.

C merhaba dünyasının iki sürümü vardı, çünkü kullanmayı puts()daha az derleme biriminde bağlayabileceğini düşündüm .

Windows'da çoğaltmayı denemek istiyorsanız, kullandığım kaynaklar şunlardır:

printf.c:

#include <stdio.h>
int main() {
  printf("Hello, world!\n");
}

puts.c:

#include <stdio.h>
int main() {
  puts("Hello, world!");
}

rust.rs

fn main() {
    println!("Hello, world!");
}

Ayrıca, farklı miktarlarda hata ayıklama bilgilerinin veya farklı optimizasyon düzeylerinin de bir fark yaratacağını unutmayın. Ama büyük bir fark görüyorsanız bunun statik ve dinamik bağlantıdan kaynaklandığını düşünüyorum.


27
gcc tam olarak printf yapabilecek kadar zekidir -> ikamenin kendisini koyar, bu yüzden sonuçlar aynıdır.
bluss

6
2018'den itibaren adil bir karşılaştırma yapmak istiyorsanız, çalıştırılabilirleri "şeritlemeyi" unutmayın, çünkü sistemimdeki bir Merhaba dünya Rust yürütülebilir 5.3MB'tır, ancak tüm hata ayıklama sembollerini kaldırdığınızda bunun% 10'undan daha azına düşer ve böyle.
Matti Virkkunen

MattiVirkkunen: 2020'de hala böyle; doğal boyut daha küçük görünüyor (5.3M'ye yakın hiçbir yerde), ancak sembollerin koda oranı hala oldukça aşırı. Hata ayıklama yapısı, CentOS 7'deki Rust 1.34.0'daki varsayılan seçenekler, 1.6M'den 190K'ya strip -sdüşer. Salimli yapı (varsayılan artı opt-level='s', lto = trueve panic = 'abort'büyüklüğünü en aza indirmek için) 623K den 158K düşer.
ShadowRanger

Statik ve dinamik elmaları nasıl ayırt edebilirim? İkincisi sağlıklı görünmüyor.
LF

30

Cargo ile derlerken dinamik bağlantı kullanabilirsiniz:

cargo rustc --release -- -C prefer-dynamic

Bu, şimdi dinamik olarak bağlı olduğu için ikili dosyanın boyutunu önemli ölçüde azaltacaktır.

Linux'ta, en azından şu stripkomutu kullanarak sembollerin ikilisini de çıkarabilirsiniz :

strip target/release/<binary>

Bu, çoğu ikili dosyanın yaklaşık boyutunu yarıya indirir.


8
Sadece bazı istatistikler, merhaba dünyasının varsayılan yayın sürümü (linux x86_64). 3,5 M, tercih edilen dinamik 8904 B ile 6392 B soyulmuş
Zitrax

30

Bir Rust ikili dosyasının boyutunu küçültmenin tüm yollarına genel bir bakış için min-sized-rustveri havuzuna bakın .

İkili boyutu azaltmak için geçerli üst düzey adımlar şunlardır:

  1. Rust 1.32.0 veya daha yenisini kullanın ( jemallocvarsayılan olarak dahil değildir )
  2. Aşağıdakileri şuraya ekle: Cargo.toml
[profile.release]
opt-level = 'z'     # Optimize for size.
lto = true          # Enable Link Time Optimization
codegen-units = 1   # Reduce number of codegen units to increase optimizations.
panic = 'abort'     # Abort on panic
  1. Kullanarak yayın modunda oluşturun cargo build --release
  2. stripOrtaya çıkan ikili üzerinde çalıştırın .

nightlyRust kullanarak yapılabilecek daha çok şey var , ancak min-sized-rustkararsız özelliklerin kullanımı nedeniyle zamanla değiştiği için bu bilgileri bırakacağım .

#![no_std]Rust'ları kaldırmak için de kullanabilirsiniz libstd. Ayrıntılar min-sized-rustiçin bakınız.


-10

Bu bir özellik, bir hata değil!

Kütüphane sürüm uyumluluğunu sağlamak için programda kullanılan kütüphane sürümlerini ( projenin ilişkili Cargo.toml dosyasında ) (örtük olanları bile) belirtebilirsiniz . Bu ise belirli kitaplığın yürütülebilir dosyaya statik olarak bağlı olmasını ve büyük çalışma zamanı görüntüleri oluşturmasını gerektirir.

Hey, artık 1978 değil - birçok insanın bilgisayarlarında 2 MB'den fazla RAM var :-)


9
kütüphane sürümlerini belirtin [...] belirli kütüphanenin statik olarak bağlı olmasını gerektirir - hayır, içermez. Kütüphanelerin tam sürümlerinin dinamik olarak bağlandığı yerlerde çok sayıda kod vardır.
Shepmaster
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.