2016-07-25 6 views
6

टुकड़ा पर विचार करेंक्या किसी ऑब्जेक्ट को किसी दिन किसी स्थानांतरित करने के दौरान जंग-बिट प्रतिलिपि को अनुकूलित कर सकते हैं?

struct Foo { 
    dummy: [u8; 65536], 
} 

fn bar(foo: Foo) { 
    println!("{:p}", &foo) 
} 

fn main() { 
    let o = Foo { dummy: [42u8; 65536] }; 
    println!("{:p}", &o); 
    bar(o); 
} 

कार्यक्रम का एक विशिष्ट result

0x7fffc1239890 
0x7fffc1229890 

जहां पते अलग-अलग हैं।

स्पष्ट रूप से, बड़े सरणी dummy की प्रतिलिपि बनाई गई है, जैसा कि संकलक के चाल कार्यान्वयन में अपेक्षित है। दुर्भाग्यवश, इसमें गैर-मामूली प्रदर्शन प्रभाव हो सकता है, क्योंकि dummy एक बहुत बड़ी सरणी है। यह प्रभाव लोगों को इसके बजाय संदर्भ द्वारा गुजरने का तर्क चुनने के लिए मजबूर कर सकता है, भले ही कार्य वास्तव में तर्क को "उपभोग" करता है।

FooCopy प्राप्त नहीं करता है, ऑब्जेक्ट o स्थानांतरित हो गया है। चूंकि जंग ने ऑब्जेक्ट की पहुंच को मना कर दिया है, इसलिए bar को मूल ऑब्जेक्ट o "पुन: उपयोग करने" के लिए क्या रोक रहा है, जिससे संकलक संभावित रूप से महंगे बिट-वार प्रतिलिपि उत्पन्न कर सकता है? क्या कोई मौलिक कठिनाई है, या क्या हम इस बिट-वार प्रतिलिपि को अनुकूलित करने के लिए किसी दिन संकलक को देखेंगे?

+7

रुस्टक चाल को अनुकूलित करता है। ऐसा इस मामले में ऐसा नहीं कर रहा है, शायद इसलिए कि llvm ने इनलाइन बार नहीं किया था। यह भी हो सकता है क्योंकि आप सूचक मानों का पालन करने की कोशिश कर रहे हैं, और llvm यह सुनिश्चित नहीं है कि यह अनुकूलित करने के लिए सुरक्षित है या नहीं। मैंने इसे ': पी' प्रिंट के बिना कोशिश की और इसके बजाय परीक्षण :: black_box का उपयोग किया, और कॉपी असेंबली से गायब हो गई। – Manishearth

+0

@ मनीशेर्थ 'बार' रेखांकित हो रहा है। एलएलवीएम बड़े सरणी की चाल को हटाने में बस खराब है। – Veedrac

उत्तर

13

यह देखते हुए कि जंग में (सी या सी ++ के विपरीत) किसी मूल्य का पता नहीं माना जाता है, भाषा के मामले में कुछ भी नहीं है जो प्रतिलिपि की रोकथाम को रोकता है।

हालांकि, आज rustc कुछ भी अनुकूलित नहीं करता है: सभी अनुकूलन एलएलवीएम को सौंपे जाते हैं, और ऐसा लगता है कि आपने एलएलवीएम ऑप्टिमाइज़र की सीमा को मारा है (यह स्पष्ट नहीं है कि यह सीमा एलवीवीएम सी के अर्थशास्त्र के करीब है या नहीं बस एक चूक)।

तो, इसके लिए कोड निर्माण को सुधारने के दो रास्ते हैं: इस अनुकूलन (यदि संभव हो)

  • शिक्षण rustc इस अनुकूलन (प्रदर्शन करने के लिए अनुकूलन गुजरता अब rustc लिए आ रहे हैं प्रदर्शन करने के लिए

    • शिक्षण LLVM कि यह MIR)

    है, लेकिन अब के लिए आप बस ढेर पर आवंटित किए जाने से इस तरह बड़ी वस्तुओं से बचने के लिए चाहते हो सकता है, उदाहरण के लिए यह Box कर सकते हैं।

  • +5

    एमआईआर ऑप्टिमाइज़ेशन पास का बोलना, पहला एक आसान स्थान गंतव्य प्रचार पास होगा: https://github.com/rust-lang/rust/pull/34693। ट्रैकिंग समस्या https://github.com/rust-lang/rust/issues/32966 है। – eddyb

    +1

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

    +0

    @MichaelYounkin: मैं आंशिक रूप से सहमत हूं। समस्या यह है कि ढेर पर कुछ बार प्रतिलिपि बनाई गई बड़ी वस्तुएं आसानी से स्टैक-ओवरफ्लो की ओर ले जाती हैं, खासकर डीबग लक्ष्यों के साथ जहां अनुकूलन नहीं होते हैं। यदि बफर बहुत बड़ा है, तो गतिशील आवंटन की लागत को बफर को स्वयं शुरू करने की लागत से बौना होना चाहिए। –

    संबंधित मुद्दे