जंग निष्पादन क्यों इतने विशाल हैं?


153

बस जंग लगने और प्रलेखन के पहले दो अध्यायों को पढ़ने के बाद, मैं दृष्टिकोण और जिस तरह से उन्होंने भाषा को विशेष रूप से दिलचस्प परिभाषित किया है। इसलिए मैंने अपनी उंगलियों को गीला करने का फैसला किया और हैलो दुनिया के साथ शुरुआत की ...

मैंने विंडोज 7 x64, btw पर ऐसा किया।

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

जारी करने cargo buildऔर परिणाम को देखने के बाद targets\debugमैंने पाया कि परिणाम .exe3MB है। कुछ खोज के बाद (कार्गो कमांड लाइन के झंडे का प्रलेखन मुश्किल है ...) मुझे --releaseविकल्प मिला और रिलीज बिल्ड बनाया। मेरे आश्चर्य के लिए, .exe का आकार केवल एक तुच्छ राशि से छोटा हो गया है: 3MB के बजाय 2.99MB।

इसलिए, मैं कबूल करता हूं कि मैं एक नौसिखिया रूस्ट और उसके पारिस्थितिकी तंत्र के लिए हूं, मेरी उम्मीद यह थी कि एक सिस्टम प्रोग्रामिंग भाषा कुछ कॉम्पैक्ट का उत्पादन करेगी।

क्या कोई इस बात पर विस्तार से बता सकता है कि जंग किस चीज का संकलन है, यह कैसे संभव हो सकता है कि यह 3 लाइनर प्रोग्राम से इतनी बड़ी छवियां पैदा करता है? क्या यह एक वर्चुअल मशीन के लिए संकलन है? क्या कोई स्ट्रिप कमांड है जो मुझे याद है (रिलीज बिल्ड के अंदर डिबग की जानकारी?) कुछ और जो समझने की अनुमति दे सकता है कि क्या हो रहा है?


4
मुझे लगता है कि 3Mb में न केवल हैलो वर्ल्ड है, बल्कि प्लेटफॉर्म के लिए सभी आवश्यक वातावरण भी है। यही बात Qt के साथ देखी जा सकती है। इसका मतलब यह नहीं है कि यदि आप 6-लाइन प्रोग्राम लिखते हैं तो आकार 6 एमबी हो जाएगा। यह 3Mb पर रहेगा और उसके बाद बहुत धीरे-धीरे बढ़ेगा।
आंद्रेई निकोलेन्को

8
@AndreiNikolaenko मुझे इसकी जानकारी है। लेकिन यह संकेत देता है कि या तो वे पुस्तकालयों को सी के रूप में नहीं संभालते हैं, केवल एक छवि के लिए जो आवश्यक है उसे जोड़ते हैं या कुछ और चल रहा है।
BitTickler

@ user2225104 मेरा जवाब देखें, RUST सी (या इसी तरह) तरीके से पुस्तकालयों को सी करता है, लेकिन डिफ़ॉल्ट रूप से सी आपके प्रोग्राम में स्थिर पुस्तकालयों को संकलित नहीं करता है (कम से कम, सी ++ पर)।
एस्फोटो


1
क्या यह अब पुराना हो गया है? रस्टक संस्करण के साथ 1.35.0 और कोई क्लि विकल्प नहीं है जो मुझे एक एक्सई मिलता है जो आकार में 137kb है। क्या यह स्वतः गतिशील रूप से जुड़ा हुआ है या इस बीच कुछ और हुआ है?
itmuckel

जवाबों:


139

जंग अपने कार्यक्रमों को संकलित करने के लिए स्थैतिक लिंकिंग का उपयोग करती है, जिसका अर्थ है कि सरलतम Hello world!कार्यक्रम के लिए आवश्यक सभी पुस्तकालयों को आपके निष्पादन योग्य में संकलित किया जाएगा। इसमें रस्ट रनटाइम भी शामिल है।

रूस्ट को गतिशील रूप से लिंक कार्यक्रमों के लिए बाध्य करने के लिए, कमांड-लाइन तर्कों का उपयोग करें -C prefer-dynamic; इसका परिणाम बहुत छोटे फ़ाइल आकार में होगा, लेकिन रनटाइम लायब्रेरी (इसके रनटाइम सहित) को रनटाइम के लिए आपके प्रोग्राम के लिए उपलब्ध होने की आवश्यकता होगी। इसका अनिवार्य रूप से मतलब है कि आपको उन्हें प्रदान करने की आवश्यकता होगी यदि कंप्यूटर उनके पास नहीं है, तो आपके मूल रूप से जुड़े हुए प्रोग्राम की तुलना में अधिक जगह लेने के लिए ऊपर ले जाता है।

पोर्टेबिलिटी के लिए, मैं अनुशंसा करता हूं कि यदि आप कभी भी अपने कार्यक्रमों को दूसरों को वितरित करने के लिए कर रहे हैं तो आप जिस तरह से कर रहे हैं, उस तरह से आप स्टिक लाइब्रेरी और रनटाइम लिंक करेंगे।


4
@ user2225104 कार्गो के बारे में अनिश्चित, लेकिन गिटहब पर इस बग रिपोर्ट के अनुसार , यह दुर्भाग्य से संभव नहीं है।
एस्फोटो

2
लेकिन जैसे ही आपके पास एक सिस्टम पर 2 से अधिक जंग
निष्कासन होते हैं

15
मुझे नहीं लगता कि स्थैतिक लिंकिंग विशाल हेलो-वर्ल्ड की व्याख्या करता है। क्या यह केवल उन पुस्तकालयों के हिस्सों में लिंक नहीं होना चाहिए जो वास्तव में उपयोग किए जाते हैं, और हेलो-वर्ल्ड लगभग कुछ भी नहीं का उपयोग करता है?
मैक्सबी

8
बिटकैलरcargo rustc [--debug or --release] -- -C prefer-dynamic
जैच

3
@ डोरबॉस आपको बहुत बहुत धन्यवाद। मैं इस संबंधित RFC पर नज़र रख रहा हूं । यह वास्तव में अफ़सोस की बात है क्योंकि रस्ट भी सिस्टम प्रोग्रामिंग को लक्षित करता है।
फ्रेंकलिन यू

62

मेरे पास प्रयास करने के लिए कोई विंडोज सिस्टम नहीं है, लेकिन लिनक्स पर, एक संकलित रस्ट हैलो दुनिया वास्तव में समतुल्य सी से छोटी है। यदि आप आकार में एक बड़ा अंतर देख रहे हैं, तो यह संभवतः इसलिए है क्योंकि आप रस्ट निष्पादन योग्य लिंक कर रहे हैं सांख्यिकीय रूप से और C एक गतिशील रूप से।

डायनामिक लिंकिंग के साथ, आपको सभी गतिशील पुस्तकालयों का आकार भी ध्यान में रखना होगा, न कि केवल निष्पादन योग्य।

इसलिए, यदि आप सेब की तुलना सेब से करना चाहते हैं, तो आपको यह सुनिश्चित करने की आवश्यकता है कि दोनों गतिशील हैं या दोनों स्थिर हैं। अलग-अलग कंपाइलरों में अलग-अलग डिफॉल्ट्स होंगे, इसलिए आप कंपाइलर डिफॉल्ट्स पर एक ही परिणाम उत्पन्न करने के लिए भरोसा नहीं कर सकते।

यदि आप रुचि रखते हैं, तो यहां मेरे परिणाम हैं:

-rw-r - r-- 1 aij aij 63 अप्रैल 5 14:26 Printf.c
-rxxr-xr-x 1 aij aij 6696 Apr 5 14:27 Printf.dyn
-rxxr-xr-x 1 aij 829344 अप्रैल 5 14:27 Printf.static
-rw-r - r-- 1 aij aij 59 अप्रैल 5 14:26 puts.c
-rxxr-xr-x 1 aij aij 6696 अप्रैल 5 14:27 puts.dyn
-rwxr-xr-x 1 aij aij 829344 अप्रैल 5 14:27 पुश्तैनी
-rxxr-xr-x 1 aij aij 8712 Apr 5 14:28 जंग।बदन
-rw-r - r-- 1 aij aij 46 अप्रैल 5 14:09 जंग
-rxxr-xr-x 1 aij aij 661496 Apr 5 14:28 rust.static

ये जीसीसी (Debian 4.9.2-10) 4.9.2 के साथ संकलित और rustc 1.0.0-रात (d17d6e7f1 2015/04/02) (बनाया 2015/04/03), डिफ़ॉल्ट विकल्प के साथ दोनों और के साथ कर रहे थे -staticजीसीसी के लिए और -C prefer-dynamicके लिए rustc।

मेरे पास C हैलो दुनिया के दो संस्करण थे क्योंकि मैंने सोचा था कि puts()कम संकलन इकाइयों में लिंक का उपयोग किया जा सकता है।

यदि आप इसे Windows पर पुन: प्रस्तुत करने का प्रयास करना चाहते हैं, तो यहां वे स्रोत हैं जिनका मैंने उपयोग किया है:

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!");
}

इसके अलावा, ध्यान रखें कि डिबगिंग की अलग-अलग मात्रा, या अलग-अलग ऑप्टिमाइज़ेशन स्तरों से भी फर्क पड़ेगा। लेकिन मुझे उम्मीद है कि अगर आप स्थैतिक बनाम गतिशील लिंकिंग के कारण बहुत बड़ा अंतर देख रहे हैं।


27
जीसीपी प्रिंटफ के लिए पर्याप्त स्मार्ट है -> प्रतिस्थापन ही डालता है, इसलिए परिणाम समान हैं।
bluss

6
2018 तक, यदि आप चाहते हैं कि एक निष्पक्ष तुलना "निष्पादन" को याद रखें, तो हैलो वर्ल्ड के रूप में, मेरे सिस्टम पर जंग निष्पादन योग्य 5.3MB है, लेकिन जब आप सभी डिबग प्रतीकों को हटाते हैं, तो यह 10% से कम हो जाता है इस तरह के।
मैटी विर्ककुनेन

@ माटी विर्ककुनेन: अभी भी 2020 में मामला; प्राकृतिक आकार छोटा लगता है (5.3M के पास कहीं भी नहीं है), लेकिन कोड के प्रतीकों का अनुपात अभी भी बहुत चरम है। डीबग बिल्ड, विशुद्ध रूप से डिफ़ॉल्ट विकल्प रूस्ट 1.34.0 पर CentOS 7, के साथ छीन लिया strip -s, 1.6M से 190K तक गिरता है। रिलीज़ बिल्ड ( डिफॉल्ट्स प्लस opt-level='s', lto = trueऔर panic = 'abort'आकार को कम करने के लिए) 623K से 158K तक गिरता है।
शैडो रेंजर

स्थिर और गतिशील सेब को कैसे भेद करें? उत्तरार्द्ध स्वस्थ नहीं लगता है।
एलएफ

30

कार्गो के साथ संकलन करते समय, आप गतिशील लिंकिंग का उपयोग कर सकते हैं:

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

यह नाटकीय रूप से बाइनरी के आकार को कम करेगा, क्योंकि यह अब गतिशील रूप से जुड़ा हुआ है।

लिनक्स पर, कम से कम, आप stripकमांड का उपयोग करके प्रतीकों के बाइनरी को भी हटा सकते हैं :

strip target/release/<binary>

यह लगभग अधिकांश बायनेरिज़ के आकार को आधा कर देगा।


8
बस कुछ आँकड़े, हैलो दुनिया का डिफ़ॉल्ट रिलीज़ संस्करण (linux x86_64)। 3.5 एम, पसंदीदा-गतिशील 8904 बी के साथ, 6392 बी छीन लिया
जीट्राक्स

30

रस्ट बाइनरी के आकार को कम करने के सभी तरीकों के अवलोकन के लिए, min-sized-rustरिपॉजिटरी देखें ।

बाइनरी आकार को कम करने के लिए वर्तमान उच्च स्तरीय चरण हैं:

  1. जंग 1.32.0 या नए का उपयोग करें (जो jemallocडिफ़ॉल्ट रूप से शामिल नहीं है )
  2. करने के लिए निम्नलिखित जोड़ें 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. का उपयोग कर रिलीज मोड में बनाएँ cargo build --release
  2. stripपरिणामी बाइनरी पर चलाएं ।

वहाँ अधिक है कि nightlyजंग का उपयोग करके किया जा सकता है , लेकिन मैं उस जानकारी को छोड़ दूंगा min-sized-rustक्योंकि यह अस्थिर सुविधाओं के उपयोग के कारण समय के साथ बदलता है।

आप #![no_std]जंग को हटाने के लिए भी उपयोग कर सकते हैं libstdmin-sized-rustविवरण के लिए देखें।


-10

यह एक विशेषता है, बग नहीं!

आप लाइब्रेरी संस्करण संगतता सुनिश्चित करने के लिए कार्यक्रम में उपयोग किए जाने वाले पुस्तकालय संस्करण ( परियोजना से जुड़ी कार्गो। फ़ाइल में ) निर्दिष्ट कर सकते हैं । दूसरी ओर, इसके लिए यह आवश्यक है कि विशिष्ट पुस्तकालय को निष्पादन योग्य से जोड़ा जाए, जिससे बड़ी रन-टाइम छवियां बन सकें।

अरे, यह 1978 नहीं है - बहुत से लोग अपने कंप्यूटर में 2 एमबी से अधिक रैम रखते हैं :-)


9
लाइब्रेरी संस्करणों को निर्दिष्ट करें [...] के लिए आवश्यक है कि विशिष्ट पुस्तकालय को सांख्यिकीय रूप से जोड़ा जाए - नहीं, यह नहीं है। बहुत सारे कोड मौजूद हैं जहां पुस्तकालयों के सटीक संस्करण गतिशील रूप से जुड़े हुए हैं।
शेमपस्टर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.