2010-06-27 15 views
8

मेरे पास एक काफी सरल सी # एप्लिकेशन है जिसने एक बड़ा हैशटेबल बनाया है। इस हैशटेबल की चाबियाँ तार हैं, और मान इंक हैं।मेमोरी उपलब्ध होने पर मेमोरी अपवाद को आउट क्यों किया जाएगा?

प्रोग्राम तब तक ठीक चलता है जब तक कि हैशटेबल में लगभग 10.3 मिलियन आइटम जोड़े नहीं जाते हैं, जब लाइन पर स्मृति त्रुटि से बाहर किया जाता है जो किसी आइटम को हैबटेबल में जोड़ता है।

कार्य प्रबंधक के अनुसार, मेरा प्रोग्राम केवल 7 9 7 एमबी मेमोरी का उपयोग कर रहा है, और अभी भी 2 जीबी से अधिक उपलब्ध है। यह एक 32-बिट मशीन है, इसलिए मुझे पता है कि केवल एक प्रक्रिया द्वारा कुल 2 जीबी का उपयोग किया जा सकता है, लेकिन यह अभी भी 1.2 जीबी छोड़ देता है कि हैशटेबल में विस्तार करने में सक्षम होना चाहिए।

मेमोरी त्रुटि से बाहर क्यों फेंक दिया जाएगा?

+1

Btw, मुझे आशा है कि आप इस के साथ सी # लेना देना नहीं है को समझने के तहत exe के प्रोजेक्ट गुण पृष्ठ पर स्थित 'पसंद करते हैं 32-बिट' चेकबॉक्स अनचेक करके इस समस्या के अपने संस्करण हल? –

+0

@ जॉन: लेकिन शायद/शायद यह .NET संबंधित है। – Wizard79

+0

@Lorenzo: यह मेरा मुद्दा है। सी # नहीं, बल्कि .NET –

उत्तर

11

सिद्धांत रूप में आप इस प्रक्रिया के लिए 2GB मिलता है, लेकिन वास्तविकता यह है कि यह 2 जीबी की संगत स्मृति है, इसलिए यदि आपकी प्रक्रिया 'स्मृति खंडित है तो आप उससे कम हो जाते हैं।

इसके अतिरिक्त मुझे संदेह है कि हैश तालिका डिफ़ॉल्ट रूप से अधिकांश डेटा संरचनाओं की तरह आकार में दोगुना हो जाएगी, जिससे इसे बढ़ने की आवश्यकता होती है जिससे टिपिंग पॉइंट आइटम जोड़ा जाता है।

यदि आप उस आकार को जानते हैं जिसे इसे समय से पहले (या उचित अनुमानित अनुमान है) तो यह कन्स्ट्रक्टर में क्षमता निर्दिष्ट करने में मदद कर सकता है।

वैकल्पिक रूप से यदि यह महत्वपूर्ण नहीं है कि यह स्मृति में है तो कुछ प्रकार का डेटाबेस समाधान बेहतर हो सकता है और यदि आप इस बिंदु तक पहुंच जाते हैं कि यह स्मृति में फिट नहीं हो सकता है तो आपको अधिक लचीलापन मिल सकता है।

+1

बिल्कुल नहीं: प्रत्येक प्रक्रिया को अपनी निजी 2 जीबी की वर्चुअल मेमोरी मेमोरी मिली है। विखंडन * प्रक्रिया * के अंदर है, क्योंकि आपकी प्रक्रिया में दो संगत स्मृति पृष्ठ वास्तव में कर्नेल के अनुरूप नहीं हो सकते हैं। – Wizard79

+0

धन्यवाद ... मैंने इसे 17 मिलियन क्षमता के साथ फिर से चलाया है, और हम देखेंगे कि यह कैसा चल रहा है। डेटा डेटाबेस से आ रहा है, लेकिन मैं प्रक्रिया को स्वयं नहीं चला सकता क्योंकि रिकर्सिव क्वेरी बहुत धीमी हैं। मैं इसके बाद प्रक्रिया करने के लिए डेटाबेस में (आइटम, नोड) के प्रत्येक इंस्टेंस को सम्मिलित कर सकता हूं, लेकिन मुझे उम्मीद है कि यह नेटवर्क की गति – Paul

+0

@Lorenzo धन्यवाद के कारण बहुत धीमी होगी, यह दर्शाता है कि यह प्रक्रिया के भीतर स्मृति विखंडन है और नहीं प्रणाली। – Davy8

4

शायद यह स्मृति विखंडन के कारण है: आपके पास अभी भी मुफ्त मेमोरी है लेकिन संगत नहीं है। मेमोरी पृष्ठों, आम तौर पर आकार में 4KB में बांटा गया है, इसलिए यदि आप 4 एमबी आवंटित, आप 1024 सन्निहित स्मृति पृष्ठों अपनी प्रक्रिया अंतरिक्ष के समाधान में की आवश्यकता होगी (वे नहीं होना है शारीरिक रूप से स्मृति के रूप में सन्निहित आभासी प्रति- है प्रक्रिया)।

हालांकि hashtable आस पास होने (जब तक यह बहुत बुरी तरह से कार्यान्वित किया जाता है) भी नहीं है, के लिए स्मृति तो शायद यह स्मृति प्रबंधक से कुछ सीमा होती है ...

0

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

3

प्रक्रिया एक्सप्लोरर (www.sysinternals.com) का उपयोग करें और अपनी प्रक्रिया के वर्चुअल एड्रेस स्पेस को देखें। "प्राइवेट बाइट्स" (जो प्रक्रिया द्वारा ली गई स्मृति की मात्रा है) के विपरीत, वर्चुअल एड्रेस स्पेस उपयोग में उच्चतम मेमोरी एड्रेस दिखाता है। अगर विखंडन उच्च है, तो यह "निजी बाइट्स" से काफी अधिक होगा।

आपके आवेदन वास्तव में है कि अधिक स्मृति की जरूरत है:

  • के लिए जा रहा पर विचार करें 64-बिट
  • /LARGEADDRESSAWARE झंडा है, जो एक 64-बिट के तहत अपने 32-बिट प्रक्रिया रैम 4 जीबी दे देंगे सक्षम करें ऑपरेटिंग सिस्टम, और 3 जीबी यदि 32-बिट विंडोज/3 जीबी फ्लैग के साथ बूट किया गया है।
1

आप बस गलत कॉलम देख रहे हैं। "कमिट साइज" कॉलम पर एक नज़र डालें, यह लगभग 2 जीबी होना चाहिए।

http://windows.microsoft.com/en-us/windows-vista/What-do-the-Task-Manager-memory-columns-mean

+0

यह विंडोज एक्सपी है ... मुझे नहीं लगता कि इसमें टास्क मैनेजर में "कमिट साइज" है – Paul

+0

यह एक अच्छा जवाब है, हालांकि अब सवाल बन जाता है: वास्तविक स्मृति उपयोग से आकार इतना बड़ा क्यों है? – Wizard79

+0

लोरेंजो: "कमिट आकार" एप्लिकेशन द्वारा उपयोग के लिए आरक्षित स्मृति की मात्रा है (यानी एक स्मृति आवंटन आदेश निष्पादित किया गया था) - इसका मतलब यह नहीं है कि इसका वास्तव में उपयोग किया जा रहा है। "निजी कामकाजी सेट" स्मृति की मात्रा है जो प्रक्रिया द्वारा आवंटित/और/दोनों का उपयोग किया गया है, जिसे अन्य प्रक्रियाओं के साथ साझा नहीं किया जा सकता है। –

1

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

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

+-------+ 
    | large |  collected less often (~1/10+ cycles) 
    +-+-------+-+    | 
    | medium |    | 
+-+-----------+-+   V 
|  small  | collected more often (~1/3 cycles) 
+---------------+ 

नोट: संख्या स्मृति से हैं, इसलिए इसे नमक के अनाज से लें।

+0

-1: आपको क्या लगता है कि वह डीबगर में चल रहा है? –

+0

मुझे स्पष्टीकरण दें- डीबग मोड में चलाना, रिलीज मोड नहीं। – Tim

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