2011-10-10 7 views
25

मैं concat के अपने खुद के संस्करण, myConcat को परिभाषित:अंतरिक्ष GHC दुभाषिया में केवल विशेष मामलों में रिसाव जब कर रही: concat <some list> !! n

module Eh where 

myConcat []   = [] 
myConcat ([]:os)  = myConcat os 
myConcat ((x:xs):os) = x : myConcat (xs:os) 

(!!!) :: [a] -> Int -> a 
xs  !!! n | n < 0 = error "negative index" 
[]  !!! _   = error "index too large" 
(x:_) !!! 0   = x 
(_:xs) !!! n   = xs !!! (n-1) 

अगर मैं GHC दुभाषिया में myConcat <some huge list> !! n करते हैं, यह 300MB/s पर मेरी स्मृति चुरा लेता है, और मैं इसे मारने के लिए इससे पहले कि यह OOM बुलाने कर सकते हैं हत्यारा। यहां ध्यान दें कि मैं Eh को "व्याख्या" के रूप में लोड करता हूं, मैं इसे लोड करने से पहले संकलित नहीं करता हूं।

 
code run in the GHC interpreter  space leak? 
myConcat (repeat [1,2,3,4]) !! (10^8) Yes 
concat (repeat [1,2,3,4]) !! (10^8) No 
myConcat (repeat [1,2,3,4]) !!! (10^8) No 
concat (repeat [1,2,3,4]) !!! (10^8) No 

अब अगर मैं संकलन Eh (ghc --make -O2 Eh.hs), और फिर दुभाषिया में लोड और इन परीक्षणों को फिर से चलाने, उनमें से कोई अंतरिक्ष रिसाव। वैसे ही अगर मैं दुभाषिया में उन्हें चलाने के बजाय प्रत्येक टेस्ट केस संकलित करता हूं।

क्या चल रहा है?


मैं जीएचसी 6.12.3 चला रहा हूं।

+0

GHCi किस संस्करण का उपयोग कर रहे हैं? मेरी मशीन पर सभी चार मामलों में निरंतर स्मृति है। मेरे पास ghc '7.0.3' या ऐसा कुछ है। – fuz

+0

मैं 6.12.3 चला रहा हूं। परीक्षण के लिए धन्यवाद! 6.12.3 पुराना है? –

+2

इतना नहीं ... – fuz

उत्तर

1

यहां मुद्दा यह कठोरता है। हास्केल में मूल्यांकन गैर-सख्त है, इसलिए गणना आमतौर पर तभी होती है जब उनके परिणामों की वास्तव में आवश्यकता होती है। इसके बजाए, एक तथाकथित थंक बनाया गया है जो अभी तक किए गए गणना का प्रतिनिधित्व करता है।

कुछ मामलों में संकलक लेकिन पता लगा सकते हैं कि गणना का परिणाम वैसे भी आवश्यकता होगी और इसलिए वास्तविक गणना द्वारा Thunks के निर्माण बदल देता है।

Haskell Wiki शायद इस बेहतर बताते हैं।

अपने myConcat फ़ंक्शन को ठीक करने के लिए आपको यह सुनिश्चित करना होगा कि यह सख्त मूल्यांकन को मैन्युअल रूप से मजबूर कर लाखों हिस्सों को नहीं बनाये। एक (नहीं बहुत सुंदर लग रही) ऐसा करने का तरीका हो सकता है:

myConcat []   = [] 
myConcat ([]:os)  = myConcat os 
myConcat ((x:xs):os) = ((:) $! x) myConcat (xs:os) 
+0

मुझे नहीं लगता कि यह मुद्दा यहां है। रिसाव केवल ghc-6.12 के साथ होता है और केवल व्याख्या कोड के साथ होता है। यदि यह केवल सख्तता थी, तो रिसाव अन्य संस्करणों के साथ भी हो सकता है, और साथ ही (अप्रत्याशित) संकलित कोड में भी होना चाहिए। मुझे 6.12 के बाइट-कोड जनरेटर में कोने-केस बग की तरह दिखता है। –

+0

शायद, लेकिन मेरा myConcat' का संस्करण तब क्यों काम करता है? एकमात्र परिवर्तन सख्त लागू है। – bseibold

+0

हां, निश्चित रूप से आलस्य में इसका एक हिस्सा है, और सही सख्तता एनोटेशन शुरू करके, रिसाव से बचा जा सकता है।मेरा मतलब यह है कि आम तौर पर, ghci द्वारा उत्पन्न बाइट-कोड मूल परिभाषा को अच्छी तरह से मानता है, इसलिए 6.12 के बाइट-कोड जनरेटर में किसी समस्या के मुकाबले रिसाव बिंदुओं का प्रकटीकरण की कठिनाई के साथ समस्या परिभाषा प्रति से। –

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