2008-09-29 12 views
6

हमारे पास कुछ ऑपरेशन हैं जहां हम बड़ी संख्या में बड़ी स्ट्रिंग कॉन्सटेनेशन कर रहे हैं, और हाल ही में मेमोरी अपवाद का सामना करना पड़ा है। दुर्भाग्यवश, कोड को डीबग करना एक विकल्प नहीं है, क्योंकि यह किसी ग्राहक साइट पर होता है।स्ट्रिंगबिल्डर की रैम खपत कैसा है?

तो, हमारे कोड के ओवरहाल को देखने से पहले, मैं पूछना चाहूंगा: बड़े तारों के लिए स्ट्रिंगबिल्डर की रैम खपत विशेषताओं क्या है?

खासकर जब वे मानक स्ट्रिंग प्रकार की तुलना करते हैं। तारों का आकार 10 एमबी से अधिक है, और हम लगभग 20 एमबी के मुद्दों में भाग लेते हैं।

नोट: यह गति के बारे में नहीं है लेकिन राम।

उत्तर

6

यहां String Concatenation vs Memory Allocation के बारे में एक अच्छा अध्ययन है।

यदि आप concatenating से बच सकते हैं, तो इसे करें!

यह एक नहीं चाहती हैं यदि आप नहीं श्रेणीबद्ध करने के लिए है, लेकिन अपने स्रोत कोड, अच्छे लग रहे पहली विधि का उपयोग करना चाहते हैं। यह के रूप में अनुकूलित किया जाएगा यदि यह एक स्ट्रिंग था।

+ = concatenating का उपयोग न करें। दृश्य के पीछे बहुत अधिक परिवर्तन हो रहे हैं, जो पहले कोड में मेरे कोड से स्पष्ट नहीं हैं। मैं स्ट्रिंग.कोनकैट() का उपयोग किसी भी ओवरलोड (2 स्ट्रिंग्स, 3 स्ट्रिंग्स, स्ट्रिंग सरणी) के साथ स्पष्ट रूप से करने की सलाह देता हूं। यह स्पष्ट रूप से दिखाएगा कि आपका कोड बिना किसी आश्चर्य के क्या करता है, जबकि स्वयं को दक्षता पर चेक रखने की अनुमति देता है।

स्ट्रिंगबिल्डर के लक्षित आकार का अनुमान लगाने का प्रयास करें।

अधिक आप जरूरत आकार का अनुमान कर सकते हैं सही, कम अस्थायी तार StringBuilder करना होगा अपने आंतरिक बफर बढ़ाने के लिए पैदा करते हैं।

प्रदर्शन एक समस्या होने पर किसी भी प्रारूप() विधियों का उपयोग न करें।

बहुत ज्यादा भूमि के ऊपर प्रारूप पार्स करने, जब आप टुकड़े से बाहर एक सरणी का निर्माण कर सकता है जब सब आप उपयोग कर रहे हैं {x} की जगह में शामिल है। प्रारूप() पठनीयता के लिए अच्छा है, लेकिन जब आप हैं, तो आपके आवेदन के पर सभी संभव प्रदर्शन निचोड़ने वाली चीजों में से एक है।

10

हर बार स्ट्रिंगबिल्डर अंतरिक्ष से बाहर चला जाता है, यह मूल बफर के आकार से दो बार एक नया बफर फिर से चलाता है, पुराने पात्रों की प्रतिलिपि बनाता है, और पुराने बफर को जीसीडी प्राप्त करने देता है। यह संभव है कि आप बस पर्याप्त उपयोग कर रहे हैं (इसे x कहते हैं) जैसे कि 2x स्मृति की तुलना में बड़ा है जिसे आवंटित करने की अनुमति है। आप अपने तारों के लिए अधिकतम लंबाई निर्धारित करना चाहते हैं, और इसे स्ट्रिंगबिल्डर के निर्माता को पास कर सकते हैं ताकि आप प्रीलोकेट कर सकें, और आप दोगुनी पुनर्वितरण की दया पर नहीं हैं।

-2

मुझे स्ट्रिंग बिल्डर के बिल्कुल मेमोरी पैटर्न के बारे में पता नहीं है लेकिन सामान्य स्ट्रिंग एक विकल्प नहीं है।

जब आप सामान्य स्ट्रिंग का उपयोग करते हैं तो प्रत्येक कॉन्सटेनेशन स्ट्रिंग ऑब्जेक्ट्स और मेमोरी खपत स्काईरकेट बनाता है, जिससे कचरा कलेक्टर को अक्सर बुलाया जाता है।

string a = "a"; 

//creates object with a 

a += "b" 

/creates object with b, creates object with ab, assings object with ab to "a" pointer 
+0

मैं आपको इस पर भरोसा करने से पहले स्ट्रिंग क्लास कार्यान्वयन की जांच करने की सलाह देता हूं। कम से कम जावा में, यह अब से अधिक स्मार्ट है। मैंने .NET के कार्यान्वयन की जांच नहीं की है, लेकिन मैं नहीं देख सकता कि वे एक ही अनुकूलन क्यों नहीं करेंगे। –

1

स्ट्रिगबिल्डर तारों को संयोजित करने के कारण स्मृति समस्याओं का एक बिल्कुल अच्छा समाधान है।

अपने विशिष्ट प्रश्न का उत्तर देने के लिए, स्ट्रिंगबिल्डर के पास सामान्य स्ट्रिंग की तुलना में स्थिर आकार का ओवरहेड होता है जहां स्ट्रिंग की लंबाई वर्तमान-आवंटित स्ट्रिंगबिल्डर बफर की लंबाई के बराबर होती है। बफर संभावित रूप से स्ट्रिंग के आकार से दोगुना हो सकता है, लेकिन बफर भरने तक स्ट्रिंगबिल्डर को संयोजित करते समय स्मृति आवंटन नहीं किया जाएगा, इसलिए यह वास्तव में एक उत्कृष्ट समाधान है।

स्ट्रिंग के साथ तुलना में, यह बकाया है।

string output = "Test"; 
output += ", printed on " + datePrinted.ToString(); 
output += ", verified by " + verificationName; 
output += ", number lines: " + numberLines.ToString(); 

इस कोड को चार तार कि कोड, दो और एक चर से एक तरीकों में बनाए जाते हैं में शाब्दिक रूप में जमा है, लेकिन यह छह अलग मध्यवर्ती तार जो अब और लंबे समय तक मिलता है उपयोग करता है। यदि यह पैटर्न जारी रखा जाता है, तो यह तब तक गतिशील दर पर स्मृति उपयोग को बढ़ाएगा जब तक कि जीसी इसे साफ करने में सक्षम न हो जाए।

+0

जिस व्यक्ति ने इसे कम किया है, कृपया समझाएं। – torial

3

आपको रस्सी डेटा संरचना से रूचि हो सकती है। यह आलेख: Ropes: Theory and practice उनके फायदे बताता है। शायद .NET के लिए एक कार्यान्वयन है।

[अद्यतन, टिप्पणी का जवाब देने के लिए] क्या यह कम स्मृति का उपयोग करता है? लेख में मेमोरी खोजें, आपको कुछ संकेत मिलेगा।
मूल रूप से, हां, संरचना ओवरहेड के बावजूद, क्योंकि यह आवश्यक होने पर स्मृति को जोड़ता है। स्ट्रिंगबिल्डर, पुराने बूफर को थकाते समय, एक बहुत बड़ा आवंटित करना चाहिए (जो पहले से ही खाली मेमोरी बर्बाद कर सकता है) और पुराने बूंद को छोड़ देता है (जो कचरा इकट्ठा किया जाएगा, लेकिन फिर भी औसत समय में बहुत सारी मेमोरी का उपयोग कर सकता है)।

मुझे .NET के लिए कार्यान्वयन नहीं मिला है, लेकिन कम से कम एक सी ++ कार्यान्वयन है (एसजीआई के एसटीएल: http://www.sgi.com/tech/stl/Rope.html में)। शायद आप इस कार्यान्वयन का लाभ उठा सकते हैं। ध्यान दें कि मेरे द्वारा संदर्भित पृष्ठ मेमोरी प्रदर्शन पर एक काम है।

ध्यान दें कि रस्सियां ​​सभी समस्याओं का इलाज नहीं हैं: उनकी उपयोगिता आपके बड़े तारों को कैसे बनाती है, और आप उनका उपयोग कैसे करते हैं, इस पर निर्भर करती है। लेख फायदे और कमियों को इंगित करते हैं।

+0

गति के मुकाबले रैम-वार कैसे करता है इस पर कोई डेटा? – torial

+0

मैं अपनी प्रतिक्रिया अपडेट करके जवाब देता हूं। मुझे आशा है कि आपको टिप्पणियों के जवाबों के बारे में सूचित किया जाएगा। – PhiLho