2011-09-11 9 views
7

मैं एक .NET 3.5 आवेदनबड़े तारों को संसाधित करना, क्या यह बड़ा ऑब्जेक्ट हीप फ्रैगमेंटेशन है?

  • एक समारोह जब मैं प्रोफ़ाइल एक लाख गुना
  • यह खोज & कर रहा है 1 एमबी + तार में & regex संचालन की जगह (विभिन्न आकार के तार)

चल रहा है है आवेदन मैं इन तारों की पुष्टि कर सकता हूं LOH में संग्रहीत किया जाता है लेकिन बाद में उन्हें जीसी द्वारा पुनः दावा किया जाता है, इसलिए किसी दिए गए समय में उनमें से केवल अधिकतम 10 LOH (10 थ्रेड चल रहा है) में हैं।

मेरे समझ, इन बड़ी तार LOH में स्थित हैं है, तो उनके आवंटन स्थानों की वजह से जी सी द्वारा पुन: दावा, लेकिन अभी तक किसी भी तरह (और LOH में किया जा रहा है ताकि नहीं मिल जमा) इस विखंडन का कारण बनता है हो रही है। ऑपरेशन में कोई स्मृति रिसाव होने के बावजूद यह हो रहा है।

यह 100k बार में कोई समस्या नहीं पैदा करता है, हालांकि जब यह 1 एम + तक पहुंच जाता है तो यह स्मृति अपवादों से बाहर निकलता है।

मैं चींटियों मेमोरी प्रोफाइलर उपयोग कर रहा हूँ और यह परिणाम है कि मैं जल्दी फांसी में मिल गया है:

.NET Using 70MB of 210MB total private bytes allocated in to the application 
Number of Fragments: 59 
Number of Large Fragments : 48 (99.6% of free memory) 
Largest Fragment: 9MB 
Free Space: 52% of total memory (37MB) 
Unmanaged Memory: 66% of total private memory (160MB) 
  1. क्या आपको लगता है मेरी निदान हाथ में डेटा के आधार पर सही हैं?
  2. यदि हां, तो मैं इस LOH Fragmentation समस्या को कैसे हल कर सकता हूं? मुझे उन तारों को संसाधित करना है और वे बड़े तार हैं। क्या मुझे उन्हें विभाजित करने और उस तरह की प्रक्रिया करने का कोई तरीका मिलना चाहिए? उस मामले में विभाजित तारों में रेगेक्स इत्यादि चलाना वास्तव में चुनौतीपूर्ण होगा।
+1

एक अन्य संभव समाधान: एक अलग प्रक्रिया है कि स्ट्रिंग संसाधन करता है, और प्रत्येक स्ट्रिंग (या हर 100K है कि यदि आप स्ट्रिंग्स के लिए ठीक लग रहा है, आदि) के लिए एक नई प्रक्रिया का उपयोग करें। प्रत्येक प्रक्रिया एक साफ स्लेट के साथ शुरू होता है। यह आईआईएस ऐप पूल - विखंडन को रीसायकल करने के कारणों में से एक है। – vcsjones

+0

@vcsjones, मैंने सोचा कि इससे पहले कि मैं वास्तव में और इसे ओवरकिल करता हूं :) मैं यह सुनिश्चित करना चाहता हूं कि यह कारण है। मैं जीसी के बढ़िया विवरण के लिए नया हूं इसलिए मुझे घंटों और बाद में यह नहीं पता कि मैंने वास्तव में कुछ भी हल नहीं किया है! समस्या वास्तविक समस्या को पुन: उत्पन्न करना काफी कठिन है, अगर मैं भाग्यशाली हूं तो इसमें एक या दो दिन लग सकते हैं। तो मैं ज्यादातर समय के लिए प्रोफाइलर का शब्द लेता हूं। –

+2

आप 64 बिट मोड में प्रोग्राम चलाने का प्रयास कर सकते हैं। इससे समस्या हल हो जाएगी क्योंकि वर्चुअल स्पेस बहुत बड़ा है। – xanatos

उत्तर

2
  1. हां। यह सही लगता है। LOH खंडित हो रहा है, जो रनटाइम को बड़े तारों के लिए पर्याप्त संगत स्थान आवंटित करने में असमर्थ होता है।

  2. आपके पास कुछ विकल्प हैं, मुझे लगता है कि जो भी करना सबसे आसान और प्रभावी है वह आपको चुनना चाहिए। यह सब पूरी तरह से इस पर निर्भर करता है कि यह कैसे लिखा गया है।

    1. अपने तारों को छोटे हिस्सों में तोड़ दें कि वे LOH में नहीं हैं। (85 के से कम - नोट: LOH isn't that cut-and-dry पर ऑब्जेक्ट डालने के लिए तर्क।) इससे जीसी अंतरिक्ष को पुनः प्राप्त करने में सक्षम हो जाएगा। यह किसी भी तरह से विखंडन को ठीक करने की गारंटी नहीं है - यह निश्चित रूप से अन्यथा भी हो सकता है। यदि आप तारों को छोटा करते हैं, लेकिन फिर भी LOH पर समाप्त होते हैं - तो आप समस्या को दूर कर देंगे। यह इस बात पर निर्भर करता है कि आपको 1 मिलियन से अधिक तारों को संभालने की आवश्यकता है। दूसरा नकारात्मक पक्ष है - आपको अभी भी इसे विभाजित करने के लिए स्मृति में स्ट्रिंग को लोड करना होगा, इसलिए यह LOH पर भी समाप्त होता है। से पहले आप स्ट्रिंग को कम कर देंगे, आपका एप्लिकेशन उन्हें भी लोड करता है। एक कैच -22 की तरह। EDIT: टिप्पणियों में गेबे एक बिंदु बनाता है कि यदि आप अपनी स्ट्रिंग को StringBuilder में पहले लोड कर सकते हैं, तो कवर के तहत यह LOH से चीजों को रखने के लिए अच्छा प्रयास करता है (जब तक आप ToString पर कॉल नहीं करते)।

    2. स्ट्रिंग की प्रक्रिया को एक अलग प्रक्रिया में तोड़ दें। धागे की बजाय एक प्रक्रिया का प्रयोग करें। कहने के लिए प्रत्येक प्रक्रिया का प्रयोग करें, 10 के तार, फिर प्रक्रिया को मारें और दूसरा शुरू करें। इस तरह, प्रत्येक प्रक्रिया एक साफ स्लेट के साथ शुरू होता है।इसका लाभ यह है कि यह आपके स्ट्रिंग प्रसंस्करण तर्क को नहीं बदलता है (आपको प्रसंस्करण के लिए अपने तारों को छोटा नहीं कर सकता), और # 1 में कैच -22 से बचाता है। नकारात्मकता यह है कि इसके लिए संभवतः आपके आवेदन में एक बड़ा बदलाव होना चाहिए, और मास्टर प्रक्रिया और दास प्रसंस्करण प्रक्रिया के बीच कार्य समन्वय करना आवश्यक है। चाल यह है कि मास्टर केवल इतना कह सकता है कि बड़ी स्ट्रिंग कहां है, यह इसे सीधे नहीं दे सकती है, अन्यथा आप कैच -22 पर वापस आ गए हैं।

+2

सामान्य रूप से आप शायद अपनी स्ट्रिंग को 'स्ट्रिंगबिल्डर' में लोड कर सकते हैं जो (कम से कम .NET 4.0 में) LOH से बचने के लिए बहुत सावधान है। इससे स्ट्रिंग को तोड़ना आसान हो जाएगा। दुर्भाग्यवश, आप 'स्ट्रिंगबिल्डर' पर रेगेक्स नहीं चला सकते हैं और शायद टूटे हुए तारों पर रेगेक्स को चलाने की संभावना नहीं हो सकती है। – Gabe

+0

@Gabe - यह एक बहुत अच्छा मुद्दा है। – vcsjones

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