2012-10-04 15 views
13

संभव डुप्लिकेट:
Small Haskell program compiled with GHC into huge binaryफाइलसाइज में हास्केल/जीएचसी निष्पादन योग्य इतने बड़े क्यों हैं?

हाल ही में मैंने देखा है कि कैसे बड़े हास्केल निष्पादनयोग्य हैं। नीचे दी गई सब कुछ जीएचसी 7.4.1 पर लिनक्स पर -O2 के साथ संकलित की गई थी।

  1. हैलो वर्ल्ड (main = putStrLn "Hello World!") 800 से अधिक कीबी है। strip पर चलने से 500 कीबी तक फाइलसाइज कम हो जाती है; संकलन में -dynamic भी जोड़ने से मुझे 400 कीबी के चारों ओर एक पट्टी निष्पादन योग्य के साथ छोड़ने में मदद नहीं मिलती है।

  2. पारसीक से जुड़े एक बहुत ही प्राचीन उदाहरण को संकलित करना 1.7 एमआईबी फ़ाइल उत्पन्न करता है।

    -- File: test.hs 
    import qualified Text.ParserCombinators.Parsec as P 
    import Data.Either (either) 
    
    -- Parses a string of type "x y" to the tuple (x,y). 
    testParser :: P.Parser (Char, Char) 
    testParser = do 
        a <- P.anyChar 
        P.char ' ' 
        b <- P.anyChar 
        return (a, b) 
    
    -- Parse, print result. 
    str = "1 2" 
    main = print $ either (error . show) id . P.parse testParser "" $ str 
    -- Output: ('1','2') 
    

    Parsec एक बड़ा पुस्तकालय हो सकता है, लेकिन मैं केवल एक छोटे सबसेट का उपयोग कर रहा है, और वास्तव अनुकूलित कोर से ऊपर द्वारा बनाया गया कोड निष्पादन की तुलना में नाटकीय रूप से छोटा होता है:

    $ ghc -O2 -ddump-simpl -fforce-recomp test.hs | wc -c 
    49190 (bytes) 
    

    इसलिए, यह मामला नहीं है कि वास्तव में कार्यक्रम में पारसी की एक बड़ी मात्रा वास्तव में पाई जाती है, जो मेरी प्रारंभिक धारणा थी।

ऐसे विशाल आकार के निष्पादन योग्य क्यों हैं? क्या मैं इसके बारे में कुछ कर सकता हूं (गतिशील लिंकिंग को छोड़कर)?

+0

@DanielWagner अन्य प्रश्न निश्चित रूप से संबंधित है, लेकिन यहां वर्णित तकनीकों का उपयोग करके हैलो वर्ल्ड अभी भी विशाल है। इसके अलावा: छोटे कोर कोड, जिसमें पूरे कार्यक्रम को शामिल करना चाहिए, संकलित होने पर इतना बड़ा हो जाता है? – David

+2

एक बड़ी रनटाइम प्रणाली है। – augustss

+2

@ डेविड: कोर में पूरे कार्यक्रम को शामिल नहीं किया जाता है जब तक कि सब कुछ रेखांकित नहीं हो जाता है, जो कि असंभव है। तो यह Parsec में लिंक करने जा रहा है, और जब तक आप इसे '-split-objs' के साथ नहीं बनाते (देखें [संबंधित उत्तर] (http://stackoverflow.com/a/9198223/98117)), इसे लिंक करना होगा यह सब। – hammar

उत्तर

3

मेरी समझ यह है कि यदि आप पैकेज X, से एक ही फ़ंक्शन का उपयोग करते हैं तो संपूर्ण पैकेज स्थिर रूप से लिंक हो जाता है। मुझे नहीं लगता कि जीएचसी वास्तव में फ़ंक्शन-बाय-फ़ंक्शन को लिंक करता है। (जब तक आप "विभाजित ऑब्जेक्ट्स" हैक का उपयोग नहीं करते हैं, जो "लिंकर को फिक्र करने के लिए जाता है"।)

लेकिन यदि आप गतिशील रूप से लिंक कर रहे हैं, तो इसे ठीक करना चाहिए। तो मुझे यकीन नहीं है कि यहां क्या सुझाव देना है ...

(मुझे पूरा यकीन है कि मैंने एक ब्लॉग पोस्ट देखा था जब गतिशील लिंकिंग पहली बार बाहर आई थी, हैलो वर्ल्ड को 2 केबी बाइनरी में संकलित किया गया था। जाहिर है, मुझे यह ब्लॉग नहीं मिल रहा है अब ... grr।)

क्रॉस-मॉड्यूल अनुकूलन पर भी विचार करें। यदि आप एक पारसी पार्सर लिख रहे हैं, तो संभव है कि जीएचसी सभी पार्सर परिभाषाओं को रेखांकित करे और उन्हें सबसे कुशल कोड तक सरल बनाये। और, निश्चित रूप से पर्याप्त है, हैस्केल की आपकी कुछ पंक्तियों ने 50 केबी कोर का उत्पादन किया है। मशीन कोड को संकलित करते समय 37x बड़ा होना चाहिए? मुझे नहीं पता। आप शायद अगले चरणों में उत्पादित एसटीजी और सीएमएम कोड को देखने का प्रयास कर सकते हैं। (माफ करना, मैं अपने सिर के ऊपर से संकलक झंडे को याद नहीं है ...)

+0

यह वास्तव में मामला नहीं है। यह प्रणाली पर निर्भर करता है। स्थैतिक लिंकिंग जीएचसी के साथ अधिकांश प्रणालियों पर "विभाजित ऑब्जेक्ट्स" का उपयोग होता है, ताकि आपको प्रति कार्य एक ऑब्जेक्ट मिल सके। –

+0

@ डॉनस्टवार्ट लेकिन आपको विभाजित ऑब्जेक्ट्स के साथ बनाए गए कैबल-स्थापित पुस्तकालयों को प्राप्त करने के लिए कैबल कॉन्फ़िगरेशन में स्प्लिट-ओब्जे को सक्षम करने की आवश्यकता है, है ना? –

11

प्रभावी ढंग से निष्पादन योग्य ग्लासगो हास्केल कंपाइलर द्वारा उत्पादित आप पर की

  • उपयोग ध्यान केंद्रित करने के लिए है के आकार को कम करने के लिए -dynamic विकल्प के साथ गतिशील लिंकिंग ghc को पास किया गया है ताकि मॉड्यूल कोड को साझा (गतिशील) पुस्तकालयों का उपयोग करके अंतिम निष्पादन योग्य में बंडल नहीं किया जाएगा। सिस्टम में इन जीएचसी पुस्तकालयों के साझा संस्करणों का अस्तित्व आवश्यक है!
  • अंतिम निष्पादन योग्य (एफईई) की डीबगिंग सूचनाओं को हटा रहा है।जीएनयू के binutils की पट्टी उपकरण)
  • अप्रयुक्त मॉड्यूल के हटाने के आयात द्वारा() गतिशील जोड़ने पर लाभ

सरल हैलो दुनिया उदाहरण अंतिम आकार की है 9 किबा और Parsec परीक्षण के बारे में 28 किबा (दोनों की उम्मीद नहीं है 64 बिट लिनक्स एक्जिक्यूटिव) जो मुझे उच्च स्तर की भाषा कार्यान्वयन के लिए काफी छोटा और स्वीकार्य लगता है।

+0

हैलो वर्ल्ड केवल 9 कीबी है यदि मैं 'गतिशील' से लिंक करता हूं। पारसी मामले में मुझे गतिशील संस्करण ('कैबल इंस्टॉल parsec --enable- shared --reinstall' परिणामों को कैबल में परिणाम देने में समस्याएं मिली हैं जिनके पास "पैकेज के लिए dyn पुस्तकालय" mtl-2.1.1 नहीं है " , लेकिन यह एक और सवाल करेगा। किसी भी मामले में, धन्यवाद। – David

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