2009-08-18 23 views
8

के दौरान अजीब आउट ऑफ़ मेमोरी अपवाद मैं 1264 भौतिक मेमोरी के साथ x64 सर्वर 2003 एंटरप्राइज़ पर इस कंसोल एप्लिकेशन को चलाने के लिए VSTS2008 + C# + .NET 3.5 का उपयोग कर रहा हूं।सीरियलाइजेशन

यहां मेरा कोड है, और मुझे स्टेटमेंट बफॉर्मर निष्पादित करते समय मिलता है। सरलीकृत (स्ट्रीम, टेबल), स्मृति अपवाद से बाहर है। मैंने टास्क मैनेजर के पेरर्मेंस टैब के माध्यम से मेमोरी उपयोग की निगरानी की और मुझे लगता है कि अपवाद फेंकने पर केवल 2 जी भौतिक स्मृति का उपयोग किया जाता है, इसलिए स्मृति से बाहर नहीं होना चाहिए। :-(

कोई भी विचार क्या गलत है नेट क्रमबद्धता का कोई भी सीमा

static DataTable MakeParentTable() 
    { 
     // Create a new DataTable. 
     System.Data.DataTable table = new DataTable("ParentTable"); 
     // Declare variables for DataColumn and DataRow objects. 
     DataColumn column; 
     DataRow row; 

     // Create new DataColumn, set DataType, 
     // ColumnName and add to DataTable.  
     column = new DataColumn(); 
     column.DataType = System.Type.GetType("System.Int32"); 
     column.ColumnName = "id"; 
     column.ReadOnly = true; 
     column.Unique = true; 
     // Add the Column to the DataColumnCollection. 
     table.Columns.Add(column); 

     // Create second column. 
     column = new DataColumn(); 
     column.DataType = System.Type.GetType("System.String"); 
     column.ColumnName = "ParentItem"; 
     column.AutoIncrement = false; 
     column.Caption = "ParentItem"; 
     column.ReadOnly = false; 
     column.Unique = false; 
     // Add the column to the table. 
     table.Columns.Add(column); 

     // Make the ID column the primary key column. 
     DataColumn[] PrimaryKeyColumns = new DataColumn[1]; 
     PrimaryKeyColumns[0] = table.Columns["id"]; 
     table.PrimaryKey = PrimaryKeyColumns; 

     // Create three new DataRow objects and add 
     // them to the DataTable 
     for (int i = 0; i <= 5000000; i++) 
     { 
      row = table.NewRow(); 
      row["id"] = i; 
      row["ParentItem"] = "ParentItem " + i; 
      table.Rows.Add(row); 
     } 

     return table; 
    } 

    static void Main(string[] args) 
    { 
     DataTable table = MakeParentTable(); 
     Stream stream = new MemoryStream(); 
     BinaryFormatter bformatter = new BinaryFormatter(); 
     bformatter.Serialize(stream, table); // out of memory exception here 
     Console.WriteLine(table.Rows.Count); 

     return; 
    } 

अग्रिम धन्यवाद, जॉर्ज

+1

पर भरोसा नहीं करना चाहिए (टिप्पणियों का जवाब दिया) –

+0

धन्यवाद मार्क है, आपके उत्तर इतनी महान है और जवाब के रूप में मैं इसे चिह्नित किया है। सराहना करें कि क्या आप यहां अपनी वर्चुअल मेमोरी के बारे में अपनी विशेषज्ञता साझा कर सकते हैं, http://stackoverflow.com/questions/1297797/windows-32-bit-virtual-memory-page-mapping-issue – George2

उत्तर

10

नोट:? Xml क्रमांकन प्रारूप है कि में इस्तेमाल किया गया था करने के लिए DataTable चूक ।

dt.RemotingFormat = System.Data.SerializationFormat.Binary; 
: 1. *, जो अविश्वसनीय रूप से अक्षम है कोशिश करने के लिए एक बात नए प्रारूप को स्विचिंग है

आउट-ऑफ-मेमोरी/2 जीबी; व्यक्तिगत .NET ऑब्जेक्ट्स (जैसे byte[]MemoryStream के पीछे) 2 जीबी तक सीमित हैं। शायद इसके बजाय FileStream पर लिखने का प्रयास करें?

(संपादित करें: नहीं: करने की कोशिश की है कि, अभी भी त्रुटियों)

मैं भी अगर अंतरिक्ष एक प्रीमियम है इस तरह के GZIP के रूप में आश्चर्य है कि अगर आप table.WriteXml(stream) का उपयोग कर (इस मामले में) बेहतर परिणाम प्राप्त कर सकते हैं, शायद संपीड़न के साथ।

+0

हाय मार्क, आपके मूल्यवान उत्तर के लिए धन्यवाद । बाइट [] 2 जी आकार की सीमा के लिए, क्या आप मुझे इस विषय के बारे में कुछ और दस्तावेज सुझा सकते हैं? मैं इसे कभी नहीं जानता और अधिक पृष्ठभूमि सीखना चाहता हूं। – George2

+0

"संपादित करें: nope: कोशिश की, अभी भी त्रुटियां" - आपका क्या मतलब है, अभी भी त्रुटियां? आपका मतलब है कि किस विधि में अभी भी त्रुटियां हैं? – George2

+0

मार्क, मैंने writexml का उपयोग करने की कोशिश की है और यह काम करता है। लेकिन परिणाम फ़ाइल का आकार केवल 520 एम है। यह 2 जी से बहुत कम है। आप कैसे अपना मूल कोड 2 जी सीमा हिट साबित करते हैं? – George2

1

1) ओएस x64 है, लेकिन ऐप x64 (या anycpu) है? यदि नहीं, तो यह 2 जीबी पर capped है।

2) क्या यह 'प्रारंभिक' होता है, या ऐप कुछ समय के लिए चल रहा है (यानी बाद में serializations)? क्या यह शायद बड़े ऑब्जेक्ट हीप विखंडन का परिणाम हो सकता है ...?

+0

धन्यवाद क्रिस्टोफर ए, आपकी चिंताओं के लिए, 1. मैं किसी भी सीपीयू में निर्माण करता हूं, इसलिए यह 2 जी से अधिक भौतिक स्मृति का उपभोग करने में सक्षम होना चाहिए, सही? 2. मेमोरी अपवाद से बाहर 1 मिनट के बाद होता है, विधि के बाद MakeParentTable सफल हो जाता है। तो मुझे लगता है कि यह बड़े वस्तु ढेर विखंडन का नतीजा नहीं होना चाहिए? कोई टिप्पणी? – George2

1

दिलचस्प बात यह है कि यह वास्तव में स्मृति त्रुटि देने से पहले 3.7 जीबी तक चला जाता है (विंडोज 7 x64)। जाहिर है, इसे पूरा करने के लिए उस राशि को दोगुना करने की आवश्यकता होगी।

यह देखते हुए कि आवेदन तालिका बनाने के बाद 1.65GB का उपयोग करता है, यह संभावना है कि यह 2GB byte[] (या किसी भी एक वस्तु) सीमा मार्क Gravell की (1.65GB + 2GB ~ = 3.7GB) बोल रहा है समाप्त हो रहा है

इस blog के आधार पर, मुझे लगता है कि आप WINAPI का उपयोग करके अपनी याददाश्त आवंटित कर सकते हैं, और इसका उपयोग करके अपना स्वयं का मेमोरीस्ट्रीम कार्यान्वयन लिख सकते हैं। यही है, अगर आप वास्तव में ऐसा करना चाहते थे। या पाठ्यक्रम के एक से अधिक सरणी का उपयोग करके एक लिखें :)

+0

हाय थोरिनिन, 1. बाइट के 2 जी आकार की सीमा के लिए [], मैं और जानना चाहता हूं। क्या आपके पास कोई और संबंधित दस्तावेज हैं? 2. 1.65 जीबी और 2 जीबी का मतलब है कि आपकी गणना में किसके पदचिह्न? डेटाटेबल के लिए – George2

+1

1.65 जीबी। मैं 2 जीबी सीमा (इसके अलावा यह मौजूद है) पर भी मिल सकता है http://blogs.msdn.com/joshwil/archive/2005/08/10/450202.aspx – Thorarin

+0

धन्यवाद थोरिनिन, 1. मैं 2 जीबी सीमा को समझता हूं। लेकिन आप कैसे साबित करते हैं कि 2 जीबी वास्तव में पहुंचा है? :-) 2. 1.65 जी के लिए आप इस तरह की सटीक संख्या की गणना कैसे करते हैं? :-) – George2

6

जैसा कि पहले से ही चर्चा की गई है, यह गीगाबाइट प्रकार के आकार में स्मृति के संगत ब्लॉक प्राप्त करने की कोशिश के साथ एक मौलिक मुद्दा है।

आप से (बढ़ती कठिनाई में) सीमित हो जाएगा

  1. पता स्मृति की मात्रा
    • जब से तुम 64 बिट कर रहे हैं यह आप भौतिक स्मृति 12GB, कम यह किसी भी छेद उपकरणों के लिए आवश्यक हो जाएगा प्लस किसी भी स्वैप फ़ाइल स्थान।
    • ध्यान दें कि आपको relevant PE headers that indicate it can run 64bit के साथ एक ऐप चलाना होगा या आप WoW64 के तहत चलेंगे और केवल 4 जीबी पता स्थान होगा।
    • यह भी ध्यान दें कि डिफ़ॉल्ट लक्ष्य changed in 2010, contentious change था।
  2. CLR's limitation that no single object may consume more than 2GB of space
  3. उपलब्ध स्मृति के भीतर एक संगत ब्लॉक ढूँढना।

आप पाएंगे कि आप क्योंकि धारा में समर्थन बफर एक 'दोहरीकरण' फैशन में विस्तार किया गया है और यह तेजी से बफर में जो परिणाम बड़े वस्तु ढेर में आवंटित की जा रही 2 की CLR सीमा से पहले स्थान शेष नहीं मिल सकता है । इस ढेर को अन्य ढेर (1) के समान तरीके से संकलित नहीं किया जाता है और नतीजतन 2 के तहत बफर के सैद्धांतिक अधिकतम आकार तक निर्माण की प्रक्रिया LOH को विभाजित करती है ताकि आप पर्याप्त रूप से पर्याप्त संगत ब्लॉक ढूंढ सकें ऐसा होता है।

इस प्रकार एक शमन दृष्टिकोण यदि आप पास सीमा के लिए कर रहे धारा यह निश्चित रूप से one of the constructors के माध्यम से शुरू से ही पर्याप्त स्थान है ऐसा है कि की आरंभिक क्षमता स्थापित करने के लिए है।

यह देखते हुए कि आप एक धारावाहिक प्रक्रिया के हिस्से के रूप में मेमोरी स्ट्रीम में लिख रहे हैं, यह वास्तव में धाराओं का उपयोग करने के उद्देश्य से और आवश्यक डेटा का उपयोग करने के लिए समझ में आता है।

  • यदि आप कुछ फ़ाइल आधारित स्थान पर क्रमबद्ध कर रहे हैं तो इसे सीधे उसमें स्ट्रीम करें।
  • यदि यह डेटा एक SQL सर्वर डेटाबेस में जा रहा उपयोग करने पर विचार है:
  • देखते हैं आप कहते हैं में उपयोग के लिए स्मृति में इस serializing रहे हैं, तो एक तुलना तो डेटा स्ट्रीम पर विचार जैसा कि आप साथ जाते हैं उतना ही तुलना और भिन्नता की तुलना में।
  • यदि आप बाद में इसे फिर से बनाने के लिए स्मृति में किसी ऑब्जेक्ट को बनाए रखते हैं तो यह वास्तव में एक फ़ाइल या मेमोरी मैप की गई फ़ाइल पर जा रहा है। दोनों मामलों में ऑपरेटिंग सिस्टम तब इसे सबसे अच्छी तरह से तैयार करने के लिए स्वतंत्र होता है (डिस्क कैश या पृष्ठों को मुख्य मेमोरी में और बाहर मैप किया जा रहा है) और ऐसा लगता है कि ज्यादातर लोग ऐसा करने में सक्षम हैं खुद को।
  • यदि आप ऐसा कर रहे हैं ताकि डेटा संपीड़ित किया जा सके तो स्ट्रीमिंग संपीड़न का उपयोग करने पर विचार करें। किसी भी ब्लॉक आधारित संपीड़न धारा को पैडिंग के अतिरिक्त के साथ स्ट्रीमिंग मोड में काफी आसानी से परिवर्तित किया जा सकता है। यदि आपका संपीड़न एपीआई इसका समर्थन करने का समर्थन नहीं करता है तो ऐसा करने के लिए रैपर लिखने या लिखने वाले व्यक्ति का उपयोग करने पर विचार करें।
  • यदि आप बाइट बफर को लिखने के लिए ऐसा कर रहे हैं जिसे पिन किया गया है और एक अप्रबंधित फ़ंक्शन में पास किया गया है तो इसके बजाय UnmanagedMemoryStream का उपयोग करें, यह इस प्रकार के आकार के बफर को आवंटित करने में सक्षम होने का थोड़ा बेहतर मौका है, लेकिन यह है अभी भी ऐसा करने की गारंटी नहीं है।

शायद अगर आप हमें बता क्या आप इस आकार की एक वस्तु serializing कर रहे हैं तो हम आपको बेहतर तरीके से ऐसा करने को बताने के लिए सक्षम हो सकता है के लिए।


  1. यह एक कार्यान्वयन विस्तार आप
+0

धन्यवाद ShuggyCoUk, आपका उत्तर इतना अच्छा है! मेरे यहां एक संबंधित प्रश्न है, अगर आप मदद कर सकते हैं तो सराहना करें। http://stackoverflow.com/questions/1297797/windows-32-bit-virtual-memory-page-mapping-issue – George2

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