2009-07-10 12 views
18

में 1,000 एमबी से अधिक मेमोरी आवंटित करना मुझे आश्चर्य है कि मैं अपनी 32-बिट .NET प्रक्रिया में 1,000 एमबी मेमोरी आवंटित करने में सक्षम क्यों नहीं हूं। निम्नलिखित मिनी एप्लिकेशन 1,000 एमबी आवंटित करने के बाद आउटऑफमेमरी एक्सेप्शन फेंकता है। 1,000 एमबी क्यों, और 1.8 जीबी नहीं कहें? क्या कोई प्रक्रिया-चौड़ी सेटिंग है जिसे मैं बदल सकता हूं?32-बिट .NET प्रक्रिया

static void Main(string[] args) 
{ 
    ArrayList list = new ArrayList(); 
    int i = 0; 
    while (true) 
    { 
     list.Add(new byte[1024 * 1024 * 10]); // 10 MB 
     i += 10; 
     Console.WriteLine(i); 
    } 
} 

पीएस: कचरा संग्रहण मदद नहीं करता है।

संपादित करें, मुझे यह स्पष्ट करने के लिए संपादित करें: मैंने एक सर्वर एप्लीकेशन लिखा है जो डेटाबेस/डिस्क पर लिखने से पहले बहुत बड़ी मात्रा में डेटा से संबंधित है। सब कुछ के लिए अस्थायी फाइलें बनाने के बजाय, मैंने एक मेमोरी कैश लिखा है, जो पूरी चीज को सुपर-फास्ट बनाता है। लेकिन स्मृति सीमित है, और इसलिए मैंने यह पता लगाने की कोशिश की कि सीमाएं क्या हैं। और आश्चर्य हुआ कि मेरे छोटे परीक्षण कार्यक्रम ने बिल्कुल 1000 एमबी के बाद आउटऑफमेमरी अपवाद क्यों फेंक दिया।

उत्तर

7

Win32 प्रक्रिया का आभासी पता स्थान सीमा 1.5 जीबी (पूरी तरह से सच नहीं है) है। इसके अतिरिक्त .NET ढांचे में स्मृति की% के लिए एक limiter है एक .NET प्रक्रिया का उपभोग कर सकते हैं। Machine.config में एक विशेषता स्मृति मॉडल के साथ मॉडेल तत्व है जो उपलब्ध स्मृति का% है जो एक प्रक्रिया का उपभोग कर सकता है। डिफ़ॉल्ट मान 60% है।

यदि आपके द्वारा चल रही मशीन में 2 जीबी मेमोरी है या आपने अपने BOOT.INI में/3 जीबी स्विच सक्षम नहीं किया है तो आपको प्रति प्रक्रिया ~ 1.3 जीबी मेमोरी मिल जाएगी।

मुझे केबी आलेख नहीं मिल रहा है, लेकिन अगर मुझे सही याद है तो .NET 1.x आपकी सेटिंग्स के बावजूद 1.5 जीबी (1.8 जीबी?) सीमा से परे पता नहीं लगा सकता है।

http://blogs.msdn.com/tmarq/archive/2007/06/25/some-history-on-the-asp-net-cache-memory-limits.aspx http://social.msdn.microsoft.com/Forums/en-US/clr/thread/c50ea343-b41b-467d-a457-c5a735e4dfff http://www.guidanceshare.com/wiki/ASP.NET_1.1_Performance_Guidelines_-_Caching#Configure_the_Memory_Limit

+1

धन्यवाद, यह मुझे एक विचार देता है। हालांकि, लिंक वास्तव में सहायक नहीं हैं। –

+0

केवल सर्वर सीएलआर मेमोरीलिमिट कॉन्फ़िगरेशन का उपयोग करता है। वर्कस्टेशन सीएलआर हमेशा जितनी मेमोरी प्राप्त कर सकता है उतनी मेमोरी का उपयोग करता है। – ezolotko

+0

@ezolotko - मुझे कभी पता नहीं था कि एक अंतर था। – MyItchyChin

16

स्मृति के विशाल ब्लॉक होने के कारण 64 बिट में भी एक अच्छा विचार नहीं है। आपको संगत स्मृति और विखंडन के साथ बड़ी समस्याएं मिलती हैं।

यहां समस्या एक संगत ब्लॉक ढूंढ रही है। आप 3 जीबी मोड को सक्षम करने का प्रयास कर सकते हैं (जो इसे कुछ और बाइट खोजने में मदद कर सकता है) लेकिन मैं वास्तव में इसके खिलाफ सलाह देता हूं। यहाँ उत्तर दिए गए हैं:

  • कम स्मृति
  • का प्रयोग कर एक ब्लॉग प्रविष्टि के लिए एक डेटाबेस/फाइल सिस्टम
  • उपयोग 64

तुम भी Eric Lippert's ब्लॉग को पढ़ने के लिए चाहते हो सकता (वह लगता है का उपयोग प्रत्येक सामान्य .NET प्रश्न के लिए ...)

+2

जोहान्स, अधिक पता स्थान क्यों होगा और अधिक संगत पता स्थान ढूंढना आसान नहीं होगा ??? मैं आपकी टिप्पणी से पूरी तरह उलझन में हूं। क्या तुम समझा सकते हो? –

+0

@Eric - मुझे खुशी है कि यह सिर्फ मुझे नहीं था ... –

+0

कृपया मेरी स्पष्टीकरण देखें। मैं पहले से ही डीबी/एफएस का उपयोग कर रहा हूँ। –

2

मैं हाल ही में एक 32 बिट प्रक्रिया पर .NET में मेमरी सीमा के आसपास व्यापक रूपरेखा कर रहे हैं। हम सभी इस विचार से बमबारी हो गए हैं कि हम एक .NET आवेदन में 2.4 जीबी (2^31) तक आवंटित कर सकते हैं लेकिन असुविधाजनक यह सच नहीं है :(। आवेदन प्रक्रिया में उपयोग करने के लिए बहुत अधिक जगह है और ऑपरेटिंग सिस्टम एक महान काम करता है नौकरी हमारे लिए इसका प्रबंधन करती है, हालांकि, .NET का अपना ओवरहेड लगता है जो सामान्य वास्तविक अनुप्रयोगों के लिए 600-800 एमबी के लिए जिम्मेदार है जो स्मृति सीमा को धक्का देता है। इसका मतलब है कि जैसे ही आप पूर्णांक की एक सरणी आवंटित करते हैं 1.4 जीबी, आपको आउटऑफमेमरी एक्सेप्शन()

स्पष्ट रूप से 64 बिट में, यह सीमा बाद में होती है (चलो 5 साल में चैट करें :)), लेकिन स्मृति में सबकुछ का सामान्य आकार भी बढ़ता है (मुझे लगता है शब्द वृद्धि के कारण यह ~ 1.7 से ~ 2 गुना है)।

मुझे यह सुनिश्चित करने के लिए क्या पता है कि ऑपरेटिंग सिस्टम से वर्चुअल मेमोरी विचार निश्चित रूप से आपको एक प्रक्रिया के भीतर लगभग अंतहीन आवंटन स्थान नहीं देता है। यह केवल इतना है कि पूर्ण 2.4 जीबी एक ही समय में चल रहे सभी (कई) अनुप्रयोगों को संबोधित करने योग्य है।

मुझे आशा है कि यह अंतर्दृष्टि कुछ हद तक मदद करेगी।

मैं मूल रूप से यहां से संबंधित कुछ उत्तर नहीं दिया (मैं कर रहा हूँ अभी भी एक newby इतना यकीन है कि कैसे मैं इन कड़ियों क्या करना चाहिए नहीं कर रहा हूँ):

Is there a memory limit for a single .NET process

-2

मैं सच में माफी चाहता अगर मैं नहीं मिला हूँ अपने बिंदु लेकिन:

static void Main(string[] args) 
{ 
    ArrayList list = new ArrayList(); 
    int i = 0; 
    while (true) 
    { 
     using(byte newBt = new byte[1024 * 1024 * 10]) 
     { 
      list.Add(newBt); // 10 MB 
      i += 10; 
      Console.WriteLine(i); 
     } 
    } 
} 

क्या आपने उपयोग विधि का प्रयास किया है? और यह एक बेवकूफ सवाल हो सकता है लेकिन आपने एक शाश्वत पाश क्यों बनाया? ओ यदि आप कोड स्ट्रिप को प्रतीकों का प्रयास करते हैं>।> XD।

स्रोत: http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx

+1

मैंने कोड स्वरूपण को ठीक करने के लिए अपना उत्तर संपादित कर दिया है। अगली बार जब आपको कोड पेस्ट पोस्ट करना होगा, तो इसे चुनें और CTRL + K या {} आइकन दबाएं, यह स्वचालित रूप से स्वरूपित हो जाएगा – BlackBear

+0

यह पूरी तरह से प्रश्न के बिंदु को याद करता है। अनंत लूप स्मृति विफल होने तक स्मृति आवंटित करता है, जिससे प्रक्रिया का उपभोग करने वाली अधिकतम मात्रा में स्मृति निर्धारित किया जा सकता है। आपका कोड संकलित नहीं करता है क्योंकि यह बाइट को बाइट सरणी असाइन करने का प्रयास करता है। इसके अलावा, उन उपकरणों में से कोई भी IDISposable। और यदि यह प्रत्येक पुनरावृत्ति पर स्मृति मुक्त कर देता है, तो यह परीक्षण तोड़ देगा (अंततः यह (2^31)/10 के बारे में रिपोर्ट करेगा, लेकिन उस संख्या के साथ कुछ भी नहीं होगा जिसके साथ यह आवंटित किया जा सकता है)। –

-1

मुझे लगता है कि यहां मुद्दा यह है कि इस आवेदन हर पाश यह बनाता है के साथ 10 एमबी जोड़ने हो जाएगा, और पाश है: "जबकि (सही)" यह तक इन 10MBs जोड़ने जाएगा जिसका मतलब है आवेदन बंद कर दिया गया है। तो अगर यह 100 लूप के लिए दौड़ना था तो यह रैम के करीब 1 जीबी जोड़ देगा, और मुझे लगता है कि यह 30 सेकंड से भी कम समय में ऐसा करता। मेरा मुद्दा यह है कि आप 10 मेगाबाइट की मेमोरी प्रति लूप की कोशिश कर रहे हैं, कभी खत्म होने वाले लूप में

0

आप 64-बिट आर्किटेक्चर में अपना एप्लिकेशन बनाकर ~ 2 जीबी की तुलना में अधिक मेमोरी आवंटित कर सकते हैं, जिसके लिए आप एक विजुअल स्टूडियो में नया निर्माण कॉन्फ़िगरेशन, और एप्लिकेशन का निर्माण केवल विंडोज के 64-बिट संस्करणों पर ही चलाया जाएगा। .NET में, आपके एप्लिकेशन के लिए डिफ़ॉल्ट "कोई भी CPU" बिल्ड विकल्प का उपयोग करके, मुझे लगता है कि मैं केवल ढेर से लगभग 1.5 जीबी मेमोरी आवंटित करने में सक्षम हूं (यहां तक ​​कि 64-बिट विंडोज मशीन पर भी), क्योंकि वास्तव में एप्लिकेशन जब यह "किसी भी CPU" मोड में बनाया गया है तो केवल 32-बिट मोड में चलता है। लेकिन x64 आर्किटेक्चर को संकलित करके, आप अपने आवेदन के निष्पादन के दौरान ढेर से अधिक, अधिक स्मृति आवंटित कर सकते हैं, और मैं समझाऊंगा कि आपके आवेदन के लिए x64 बिल्ड कैसे बनाएं:

फिर से, सामान्य (डिफ़ॉल्ट) आपके .NET प्रोजेक्ट में "कोई भी CPU" बिल्ड विकल्प, आपका एप्लिकेशन हमेशा 32-बिट मोड के तहत चलाया जाएगा, यहां तक ​​कि 64-बिट विंडोज ओएस पर भी। इसलिए आप आवेदन निष्पादन के दौरान लगभग 1.5 से 2 जीबी रैम मेमोरी आवंटित नहीं कर पाएंगे। अपने .NET अनुप्रयोग को सही 64-बिट मोड में चलाने के लिए, आपको बिल्ड कॉन्फ़िगरेशन मैनेजर में जाना होगा और x64 आर्किटेक्चर के लिए एक बिल्ड प्रकार बनाना होगा, और फिर उस बिल्ड प्रकार का स्पष्ट रूप से उपयोग करके x64 के लिए अपने प्रोग्राम को पुन: संकलित करना होगा। 64 निर्माण मोड विकल्प निम्न चरणों का उपयोग अपने नेट समाधान के लिए बनाया जा सकता है:

  1. दृश्य स्टूडियो में "समाधान एक्सप्लोरर" फलक, सही समाधान आइकन पर क्लिक करें और से "कॉन्फ़िगरेशन मैनेजर" विकल्प का चयन पॉप-अप मेनू। यह .NET समाधान फ़ाइल के लिए "कॉन्फ़िगरेशन प्रबंधक" संवाद विंडो खोल देगा।
  2. दाईं ओर, "कॉन्फ़िगरेशन प्रबंधक" संवाद के शीर्ष पक्ष पर, नीचे तीर पर क्लिक करें और "& ltnew & gt" विकल्प का चयन करें। यह "नया समाधान प्लेटफार्म" संवाद खुल जाएगा।
  3. "प्लेटफ़ॉर्म" विकल्प के लिए "नया समाधान प्लेटफ़ॉर्म" संवाद में, ड्रॉप-डाउन मेनू से "x64" चुनें। फिर "ओके" बटन पर क्लिक करें और नया, x64 बिल्ड विकल्प अब कॉन्फ़िगरेशन प्रबंधक संवाद में उपलब्ध होगा।
  4. फिर, "कॉन्फ़िगरेशन प्रबंधक" संवाद पर, "सक्रिय समाधान प्लेटफ़ॉर्म" ड्रॉप-डाउन मेनू में "x64" चुनें। "बंद करें" बटन पर क्लिक करें।
  5. विजुअल स्टूडियो "समाधान एक्सप्लोरर" फलक में, सीएस प्रोजेक्ट आइकन पर राइट क्लिक करें और पॉप-अप मेनू (इस मेनू के नीचे अंतिम विकल्प) से "गुण" विकल्प चुनें। यह सीएस परियोजना गुण विंडो खुल जाएगा।
  6. सीएस प्रोजेक्ट गुण विंडो के बाईं ओर, अपने कोड प्रोजेक्ट के निर्माण गुण दिखाने के लिए "बिल्ड" टैब पर क्लिक करें। इस विंडो के शीर्ष पर, ध्यान दें कि "प्लेटफ़ॉर्म" अब "x64" (डिफ़ॉल्ट "किसी भी CPU" विकल्प के विपरीत) होना चाहिए। यदि "प्लेटफ़ॉर्म" ड्रॉप-डाउन "x64" नहीं दिखाता है, तो आपको इसे अभी चुनना चाहिए।
  7. फिर बस अपना कोड बनाएं और "बिन" फ़ोल्डर में, अब आपके पास अपने 64-बिट निर्माण के साथ एक x64 फ़ोल्डर होना चाहिए।

64-बिट पर अपने आवेदन की एक 64-बिट का निर्माण का उपयोग करते हुए अगर आपके पास विंडोज ओएस अपने कार्यक्रम स्मृति के ~ 2GB की तुलना में अधिक आवंटित करने के लिए, शायद 2^64 पते के रिक्त स्थान के लिए ऊपर की अनुमति देगा (रैम और डिस्क स्थान उपलब्ध है, जो इस प्रतिक्रिया को लिखने के समय के रूप में असली सीमित कारक हैं)।

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

  1. "इस पीसी" पर राइट क्लिक करके "सिस्टम गुण" संवाद खोलें और पॉप-अप मेनू पर "गुण" विकल्प चुनकर। इसे "स्टार्ट" और gt "कंट्रोल पैनल" और gt "सिस्टम और सिक्योरिटी" और gt "सिस्टम" पर जाकर विंडोज़ (विंडोज 10, विन 2012 सर्वर, आदि ...) के बाद के संस्करणों में भी पूरा किया जा सकता है।
  2. "सिस्टम" संवाद के बाईं तरफ, "उन्नत सिस्टम गुण" विकल्प पर क्लिक करें। यह विंडोज के लिए विरासत "सिस्टम गुण" संवाद का "उन्नत" टैब दिखाएगा।
  3. "सिस्टम गुण" संवाद के "उन्नत" टैब पर, "प्रदर्शन" बॉक्स में "सेटिंग्स" बटन पर क्लिक करें। यह "प्रदर्शन विकल्प" संवाद खुल जाएगा।
  4. "प्रदर्शन विकल्प" संवाद पर, Windows मेमोरी पेज फ़ाइल के लिए वर्तमान आकार सेटिंग देखने के लिए "उन्नत" टैब पर क्लिक करें।
  5. पृष्ठ फ़ाइल आकार बढ़ाने के लिए, "बदलें" बटन पर क्लिक करें और "वर्चुअल मेमोरी" संवाद खोला जाएगा।
  6. "वर्चुअल मेमोरी" संवाद पर, "कस्टम:" ड्राइव का चयन करें, फिर "कस्टम आकार" के अंतर्गत, "प्रारंभिक" और "अधिकतम" आकार सेट करें। आप सी: ड्राइव पर अधिकतम मात्रा में खाली स्थान तक किसी भी आकार का उपयोग कर सकते हैं, लेकिन यह परिवर्तन हार्ड ड्राइव पर पृष्ठ फ़ाइल के लिए उस स्थान को आरक्षित करेगा।
  7. फिर नई सेटिंग्स को करने के लिए सभी संवादों पर "ठीक" पर क्लिक करें। फिर यह सुनिश्चित करने के लिए अपने कंप्यूटर को रीबूट करें कि सभी परिवर्तन ठीक से पूरा हो गए हैं और नई पृष्ठ फ़ाइल सेटिंग्स संचालन में हैं।

वैसे भी, मुझे आशा है कि इससे लोगों को यह समझने में मदद मिलेगी कि वे 64-बिट विंडोज मशीन पर चलते समय भी .NET अनुप्रयोग में 1.5-2 जीबी मेमोरी सीमा मुद्दे में क्यों चल सकते हैं। यह लोगों के लिए एक बहुत भ्रमित मुद्दा हो सकता है और मुझे उम्मीद है कि मेरी व्याख्या समझ में आती है। यदि आवश्यक हो तो कृपया इस उत्तर के बारे में प्रश्नों के साथ मुझे संदेश देने में संकोच न करें।

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

  • कोई संबंधित समस्या नहीं^_^