2013-02-21 127 views
8

this SO thread में, मैंने सीखा कि एक बड़े संग्रह पर seq का संदर्भ रखने से पूरे संग्रह को कचरा-संग्रह से रोका जा सकेगा।क्लोजर में 'seq` का उपयोग करने से मुझे कब बचना चाहिए?

पहला, वह धागा 200 9 से है। क्या यह अभी भी "आधुनिक" क्लोजर (v1.4.0 या v1.5.0) में सच है?

दूसरा, क्या यह समस्या आलसी दृश्यों पर भी लागू होती है? उदाहरण के लिए, (def s (drop 999 (seq (range 1000)))) कचरा कलेक्टर को अनुक्रम के पहले 999 तत्वों को सेवानिवृत्त करने की अनुमति देगा?

आखिरकार, बड़े संग्रह के लिए इस मुद्दे के आसपास एक अच्छा तरीका है? दूसरे शब्दों में, अगर मेरे पास 10 लाख तत्वों का वेक्टर था, तो क्या मैं वेक्टर को इस तरह से उपभोग कर सकता हूं कि खपत वाले हिस्सों को कचरा इकट्ठा किया जा सकता है? अगर मेरे पास 10 मिलियन तत्वों के साथ हैशपैप था तो क्या होगा?

कारण मैं पूछता हूं कि मैं काफी बड़े डेटा सेट पर काम कर रहा हूं, और मुझे वस्तुओं के संदर्भों को बनाए रखने के लिए और अधिक सावधान रहना होगा, ताकि जिन वस्तुओं की मुझे आवश्यकता नहीं है उन्हें कचरा इकट्ठा किया जा सकता है। जैसा कि है, मुझे कुछ मामलों में java.lang.OutOfMemoryError: GC overhead limit exceeded त्रुटि का सामना करना पड़ रहा है।

+0

मुझे लगता है कि @ cgrand का उदाहरण '(ड्रॉप 99 99 0 9 (वीसीसी (1000000)) ड्रॉप करें) 'हस्तक्षेप करने वाले वेक्टर और' subvec'toring के व्यवहार के कारण है। मुझे कोई आलसी नहीं है कि एक आलसी 'विपक्ष अनुक्रम ऐसा करेगा। यदि आपको एक उपवर्गक बनाए रखने के दौरान एक वेक्टर जारी करने की आवश्यकता है, तो आप सबवेक्टर को 'नए वेक्टर' में कॉपी कर सकते हैं। हालांकि, बहुत दिलचस्प सवाल है, मैं जवाब भी देखने का इंतजार कर रहा हूं! –

उत्तर

6

यह हमेशा ऐसा होता है कि यदि आप अनुक्रम के "सिर पर रखें" तो क्लोजर को सबकुछ स्मृति में रखने के लिए मजबूर किया जाएगा। इसमें कोई विकल्प नहीं है: आप अभी भी इसका संदर्भ रखते हैं।

हालांकि "जीसी ओवरहेड सीमा तक पहुंच गया" स्मृति त्रुटि से बाहर नहीं है - यह एक संकेत है कि आप एक कल्पित वर्कलोड चला रहे हैं जो ऑब्जेक्ट्स को इतनी तेजी से बना रहा है और छोड़ रहा है कि यह जीसी को धोखा दे रहा है यह सोचने में कि यह अधिभारित है।

देखें:

आप वस्तुओं पर एक वास्तविक काम का बोझ कार्रवाई की जा रही डालते हैं, तो मुझे लगता है आपको लगता है कि इस त्रुटि को किसी भी अधिक नहीं होगा देखेंगे। आप इस मामले में उपलब्ध स्मृति से बड़े आलसी अनुक्रमों को आसानी से संसाधित कर सकते हैं।

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

  • उपयोग आलसी दृश्यों और सिर
  • उपयोग विशेष संग्रह है कि आलसी लोड हो रहा है समर्थन पर पकड़ नहीं है (Datomic इस मेरा मानना ​​है कि जैसे कुछ संरचनाओं का उपयोग करता है)
  • डेटा को ईवेंट स्ट्रीम के रूप में देखें (तूफान की तरह कुछ उपयोग करके)
  • डेटा को खंडों में विभाजित करने और उन्हें एक समय में संसाधित करने के लिए कस्टम कोड लिखें।
+0

धन्यवाद, मिकरा, यह सहायक है। मैं तूफान और डाटामिक की जांच करने की उम्मीद कर रहा हूं। –

0

यदि आप बाध्यकारी में अनुक्रम का सिर रखते हैं तो आप सही हैं और इसे gc'd नहीं किया जा सकता है (और यह क्लोजर के प्रत्येक संस्करण के साथ है)। यदि आप बड़ी मात्रा में परिणाम संसाधित कर रहे हैं, तो आपको सिर पर पकड़ने की आवश्यकता क्यों है?

इसके आसपास के रास्ते के रूप में, हाँ! आलसी-सीक कार्यान्वयन जीसी भागों को पहले से ही 'संसाधित' किया जा सकता है और सीधे बाध्यकारी के भीतर से संदर्भित नहीं किया जा रहा है। बस सुनिश्चित करें कि आप अनुक्रम के सिर पर नहीं हैं।

+1

मुझे लगता है कि मुद्दा यह है कि कुछ उप-संग्रहों में मूल के लिए बाध्यकारी होने पर भी संपूर्ण मूल का संदर्भ है? उदाहरण के लिए 'सबवेक' का दस्तावेज़ीकरण पढ़ता है "... परिणामी वेक्टर शेयर मूल के साथ संरचना करता है और कोई ट्रिमिंग नहीं होती है।" मैं इसका मतलब मूल पर 'सबवेक' लपेटता हूं और बस ऑफसेट को रीमेप्स करता है, लेकिन मुझे क्लोजर के आंतरिक भाग में बहुत दूर नहीं मिला है। –

+0

@ ए। वेब, मुझे विश्वास है कि आप सही हैं और उपरोक्त उदाहरण से बनाए गए उप वेक्टर संग्रह के प्रमुख को बनाए रखेंगे। (99 99 0 9 (आलसी-सीईसी (रेंज 1000000) छोड़ें)) हालांकि (कम से कम मेरी समझ से) –

+0

'आलसी-सीक' में अनुक्रम लपेटने के बारे में कुछ भी जादू नहीं - यह केवल एक रन-फ़ंक्शन लौटाएगा इसके आसपास 'सूची *' रैपर। (इसके अलावा, 'रेंज' पहले से आलसी है।) –