2010-07-15 16 views
113

मैं हास्केल (ज्यादातर जीएचसी के साथ) में कुछ डेटा प्रकार के मूल्य को संग्रहीत करने के लिए आवश्यक स्मृति की वास्तविक मात्रा कैसे प्राप्त कर सकता हूं? क्या रनटाइम पर इसका मूल्यांकन करना संभव है (उदा। जीएचसीआई में) या क्या इसके घटकों से कंपाउंड डेटा प्रकार की स्मृति आवश्यकताओं का अनुमान लगाना संभव है?हास्केल डेटा प्रकारों की मेमोरी पदचिह्न

data Uno = Uno a 
data Due = Due a b 

उदाहरण के लिए, इन मूल्यों को कैसे याद में कई बाइट पर कब्जा करते हैं:

सामान्य में, अगर प्रकार a और b की स्मृति आवश्यकताओं जाना जाता है, इस तरह के रूप बीजीय डेटा प्रकार के स्मृति भूमि के ऊपर क्या है?

1 :: Int8 
1 :: Integer 
2^100 :: Integer 
\x -> x + 1 
(1 :: Int8, 2 :: Int8) 
[1] :: [Int8] 
Just (1 :: Int8) 
Nothing 

मैं समझता हूं कि देरी कचरा संग्रह के कारण वास्तविक स्मृति आवंटन अधिक है। आलसी मूल्यांकन के कारण यह काफी अलग हो सकता है (और थंक आकार मूल्य के आकार से संबंधित नहीं है)। सवाल यह है कि, डेटा प्रकार दिया गया है, पूरी तरह से मूल्यांकन किए जाने पर इसकी कीमत कितनी मेमोरी लेती है?

मुझे लगता है कि स्मृति आंकड़े देखने के लिए जीएचसीआई में :set +s विकल्प है, लेकिन यह स्पष्ट नहीं है कि एक मूल्य के मेमोरी पदचिह्न का अनुमान कैसे लगाया जाए।

उत्तर

145

(निम्नलिखित GHC पर लागू होता है, अन्य compilers अलग भंडारण परंपराओं का उपयोग कर सकते हैं) अंगूठे का

नियम: एक निर्माता एक हैडर के लिए एक शब्द है, और प्रत्येक क्षेत्र के लिए एक शब्द खर्च होता है। अपवाद: कोई फ़ील्ड वाला कोई कन्स्ट्रक्टर (जैसे Nothing या True) कोई स्थान नहीं लेता है, क्योंकि जीएचसी इन रचनाकारों का एक उदाहरण बनाता है और इसे सभी उपयोगों में साझा करता है।

एक शब्द 32-बिट मशीन पर 4 बाइट्स और 64-बिट मशीन पर 8 बाइट्स है।

तो उदा।

data Uno = Uno a 
data Due = Due a b 

एक Uno 2 शब्द लेता है, और एक Due लेता है 3.

Int प्रकार

data Int = I# Int# 
अब

के रूप में परिभाषित किया गया है, Int# एक शब्द लगता है, इसलिए Int में कुल 2 लेता है। अधिकांश अनबॉक्स किए गए प्रकार एक शब्द लेते हैं, अपवाद Int64#, Word64#, और Double# (32-बिट मशीन पर) जो 2 लेते हैं। जीएचसी में वास्तव में Int और Char के छोटे मानों का कैश होता है, इसलिए कई मामलों में ये कोई ढेर नहीं लेते हैं बिल्कुल जगह एक String केवल, सूची कोशिकाओं के लिए स्थान की आवश्यकता होती है जब तक आप Char s> 255.

एक Int8Int के समान प्रतिनिधित्व है का उपयोग करें। Integer इस तरह परिभाषित किया गया है:

data Integer 
    = S# Int#       -- small integers 
    | J# Int# ByteArray#     -- large integers 

तो एक छोटा सा Integer (S#) लेता है 2 शब्द है, लेकिन एक बड़ी पूर्णांक अपने मूल्य के आधार पर अंतरिक्ष के एक चर राशि लेता है। ए ByteArray# सरणी के लिए 2 शब्द (हेडर + आकार) प्लस स्पेस लेता है।

ध्यान दें कि newtype के साथ परिभाषित एक निर्माता है। newtype पूरी तरह से एक संकलन-समय विचार है, और इसमें कोई समय नहीं लगता है और रन टाइम पर कोई निर्देश नहीं है।

The Layout of Heap Objects in the GHC Commentary में अधिक जानकारी।

+1

धन्यवाद, साइमन। यह वही है जो मैं जानना चाहता था। – sastanin

+1

शीर्षलेख दो शब्द नहीं है? टैग के लिए एक, और जीसी या मूल्यांकन के दौरान उपयोग के लिए अग्रेषण सूचक के लिए एक? तो क्या यह आपके कुल में एक शब्द नहीं जोड़ता? –

+0

इसके मूल्य के आनुपातिक या इसके लॉगेरिथम के आनुपातिक? – solidsnack

3

ghc-datasize पैकेज recursiveSize फ़ंक्शन को GHC ऑब्जेक्ट के आकार की गणना करने के लिए प्रदान करता है। हालांकि ...

आकार की गणना से पहले एक कचरा संग्रह किया जाता है, क्योंकि कचरा कलेक्टर ढेर को मुश्किल बनाता है।

... तो यह अक्सर कॉल करने के लिए व्यावहारिक नहीं होगा!

How to find out GHC's memory representations of data types? और How can I determine size of a type in Haskell? देखें।

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