2011-11-05 9 views
11

मैं LOH विखंडन के बिना बड़े तारों में कितने RegExes (मिलान खोजने के लिए) चला सकता हूं?रेगेक्स, स्ट्रिंगबिल्डर और बड़े ऑब्जेक्ट हीप फ्रैगमेंटेशन

यह तो मैं उपयोग कर रहा हूँ StringBuilder तो यह तथापि के रूप में जल्द मैं मैं जिसका मतलब है कि यह LOH में हो जाएगा StringBuilder.ToString() कॉल करनी होगी उस पर एक रेगुलर एक्सप्रेशन से चलाने की आवश्यकता के रूप में LOH में नहीं है .NET फ्रेमवर्क 4.0 है।

क्या इस समस्या का कोई समाधान है? लंबे समय तक चलने वाले एप्लिकेशन के लिए यह लगभग असंभव है जो इस तरह के बड़े तारों और RegExes से संबंधित है।

एक आइडिया इस समस्या को हल करने के लिए: एक ओर जहां इस समस्या के बारे में सोच

, मुझे लगता है कि मैं एक गंदा समाधान मिल गया।

किसी दिए गए समय में मेरे पास केवल 5 तार हैं और इन 5 तारों (85 केबी से बड़े) RegEx.Match पर पारित किए जाएंगे।

के बाद से विखंडन होती है क्योंकि नई वस्तुओं LOH में खाली स्थान को फिट नहीं होगा, इस समस्या का समाधान करना चाहिए:

  1. PadRight एक अधिकतम करने के लिए सभी स्ट्रिंग्स। स्वीकार किए जाते हैं आकार, के 1024KB कहना
  2. तो सभी नए तार कर पहले ही खाली कर दिया करने के लिए स्मृति फिट होगा के रूप में पिछले स्ट्रिंग क्षेत्र से बाहर पहले से ही है के द्वारा (मैं StringBuider के साथ ऐसा करने की आवश्यकता हो सकती)
  3. क्योंकि किसी भी विखंडन वहाँ नहीं होगा चलो ऑब्जेक्ट आकार हमेशा समान होता है इसलिए मैं केवल दिए गए समय पर 1024 * 5 आवंटित करूंगा, और इन स्ट्रिंग्स के बीच LOH में ये स्थान साझा किया जाएगा।

मैं इस डिजाइन करता है, तो अन्य बड़े वस्तुओं जो आवेदन शायद एक भी बदतर विखंडन के साथ 1024 KB तार के बहुत सारे आवंटित करने के लिए कारण होगा LOH में इस स्थान का आवंटन क्या होता है के साथ सबसे बड़ी समस्या यह लगता है। fixed कथन मदद कर सकता है हालांकि मैं वास्तव में एक नई स्ट्रिंग बनाने के बिना RegEx को एक निश्चित स्ट्रिंग कैसे भेज सकता हूं जो एक निश्चित स्मृति पते में स्थित नहीं है?

इस सिद्धांत के बारे में कोई विचार? (दुर्भाग्य से मैं आसानी से समस्या का पुनरुत्पादन नहीं कर सकता, मैं आमतौर पर परिवर्तनों का निरीक्षण करने के लिए एक मेमोरी प्रोफाइलर का उपयोग करने की कोशिश कर रहा हूं और यह सुनिश्चित नहीं करता कि मैं किस प्रकार का पृथक परीक्षण केस इस के लिए लिख सकता हूं)

+2

क्या आप निश्चित हैं कि बड़ी वस्तु ढेर खंडित हो रही है? मैं बड़े (कई सौ किलोबाइट्स) तारों के साथ बहुत सारे काम करता हूं, और मैंने कभी भी LOH विखंडन समस्या में भाग नहीं लिया है। –

+1

हाँ मुझे यकीन है। आवेदन को वास्तविक प्रभाव देखने के लिए भूख लगी और लंबे समय तक चलने की जरूरत है। यदि आप वास्तव में स्मृति प्रोफाइलिंग करते हैं तो आप देख सकते हैं कि यह आपको प्रभावित कर रहा है लेकिन आपके ऐप को क्रैश करने के लिए पर्याप्त नहीं है। –

+1

हाँ, यह आसान है। एक वसा सौ रुपये आपको 64-बिट ऑपरेटिंग सिस्टम खरीदता है। कोई भी प्रोग्रामिंग प्रयास उस से मेल नहीं खा सकता है। –

उत्तर

6

ठीक है, यहां मेरा प्रयास इस समस्या को काफी सामान्य तरीके से हल करता है लेकिन कुछ स्पष्ट सीमाओं के साथ। चूंकि मैंने कहीं भी यह सलाह नहीं देखी है और हर कोई LOH फ्रैगमेंटेशन के बारे में चिंतित है, मैं यह पुष्टि करने के लिए कोड साझा करना चाहता हूं कि मेरा डिज़ाइन और धारणाएं सही हों।

थ्योरी:

  1. एक साझा भारी StringBuilder बनाना होगा (यह बड़ा तार पढ़ा है कि हम नदियों से पढ़ने के स्टोर करने के लिए है) - new StringBuilder(ChunkSize * 5);
  2. एक बड़े पैमाने पर स्ट्रिंग बनाएँ (से भी बड़ा हो गया है अधिकतम स्वीकार्य आकार), खाली जगह के साथ शुरू किया जाना चाहिए। - नई स्ट्रिंग ('', चंकसाइज * 10);
  3. पिन स्ट्रिंग ऑब्जेक्ट मेमोरी ताकि जीसी इसके साथ गड़बड़ न करे। GCHandle.Alloc(pinnedText, GCHandleType.Pinned)।भले ही LOH ऑब्जेक्ट्स सामान्य रूप से पिन किए जाते हैं, यह प्रदर्शन में सुधार करने लगता है। हो सकता है कि क्योंकि unsafe कोड
  4. पढ़ें साझा StringBuilder में धारा और pinnedText तो असुरक्षित प्रति यह indexers
  5. का उपयोग करके रेगुलर एक्सप्रेशन से

को pinnedText पास इस कार्यान्वयन नीचे कोड सिर्फ वहाँ की तरह काम करता साथ का कोई LOH है आवंटन। मैं भी एक स्मृति प्रोफाइलर के साथ परिणाम की पुष्टि अगर मैं new string(' ') आवंटन करने के लिए एक स्थिर StringBuilder या StringBuilder.ToString() का उपयोग कोड का उपयोग कर के बजाय स्विच outofmemory exception

साथ दुर्घटनाग्रस्त होने से पहले 300% कम स्मृति आवंटित कर सकते हैं इसमें कोई LOH विखंडन है कि वहाँ, कार्यान्वयन। मुझे अभी भी समझ में नहीं आता है कि RegEx किसी भी अप्रत्याशित समस्याओं का कारण क्यों नहीं बनता है। मैंने विभिन्न और महंगी RegEx पैटर्न के साथ भी परीक्षण किया और परिणाम समान हैं, कोई विखंडन नहीं है।

कोड:

http://pastebin.com/ZuuBUXk3

using System; 
using System.Collections.Generic; 
using System.Runtime.InteropServices; 
using System.Text; 
using System.Text.RegularExpressions; 

namespace LOH_RegEx 
{ 
    internal class Program 
    { 
     private static List<string> storage = new List<string>(); 
     private const int ChunkSize = 100000; 
     private static StringBuilder _sb = new StringBuilder(ChunkSize * 5); 


     private static void Main(string[] args) 
     { 
      var pinnedText = new string(' ', ChunkSize * 10); 
      var sourceCodePin = GCHandle.Alloc(pinnedText, GCHandleType.Pinned); 

      var rgx = new Regex("A", RegexOptions.CultureInvariant | RegexOptions.Compiled); 

      try 
      { 

       for (var i = 0; i < 30000; i++) 
       {     
        //Simulate that we read data from stream to SB 
        UpdateSB(i); 
        CopyInto(pinnedText);     
        var rgxMatch = rgx.Match(pinnedText); 

        if (!rgxMatch.Success) 
        { 
         Console.WriteLine("RegEx failed!"); 
         Console.ReadLine(); 
        } 

        //Extra buffer to fragment LoH 
        storage.Add(new string('z', 50000)); 
        if ((i%100) == 0) 
        { 
         Console.Write(i + ","); 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.ToString()); 
       Console.WriteLine("OOM Crash!"); 
       Console.ReadLine(); 
      } 
     } 


     private static unsafe void CopyInto(string text) 
     { 
      fixed (char* pChar = text) 
      { 
       int i; 
       for (i = 0; i < _sb.Length; i++) 
       { 
        pChar[i] = _sb[i]; 
       } 

       pChar[i + 1] = '\0'; 
      } 
     } 

     private static void UpdateSB(int extraSize) 
     { 
      _sb.Remove(0,_sb.Length); 

      var rnd = new Random(); 
      for (var i = 0; i < ChunkSize + extraSize; i++) 
      { 
       _sb.Append((char)rnd.Next(60, 80)); 
      } 
     } 
    } 
} 
0

आप अपना काम कर सकते हैं एक ऐपडोमेन जो समय पर कुछ बिंदुओं पर उतार दिया जाता है?

+0

बात यह है कि जब तक आप किसी साझा स्टोरेज का उपयोग नहीं करते हैं और डेटा को स्मृति या फ़ाइल से सीधे स्ट्रीम के रूप में पढ़ते हैं, तब भी आपको परिणाम साझा करने की आवश्यकता होती है, फिर भी आपको एक ही समस्या है । क्योंकि यदि आप किसी भी तरह से रिमोटिंग का उपयोग करते हैं तो आप फिर से बड़े एरे या तार बनायेंगे जो LOH पर जाएंगे और अब दोनों एपडोमेन में होंगे। मेमोरी साझा करना, मेमोरी मैप किए गए फाइल इत्यादि वास्तव में एक समाधान है लेकिन यह वास्तव में एक बड़े अनुप्रयोग में वास्तव में जटिल है और काफी प्रदर्शन हिट मिला है। –

0

एक वैकल्पिक रेग-पूर्व प्रदर्शन के कुछ रास्ता खोजने के लिए होगा एक गैर सरणी आधारित डेटा संरचना पर मेल खाता है। दुर्भाग्यवश, एक त्वरित Google स्ट्रीम आधारित रेग-पूर्व पुस्तकालयों के संदर्भ में ज्यादा नहीं लाया। मुझे लगता है कि reg-ex algorithm को बहुत सी बैक ट्रैकिंग करने की आवश्यकता होगी, जो स्ट्रीम द्वारा समर्थित नहीं है।

क्या आपको नियमित रूप से नियमित अभिव्यक्तियों की पूर्ण शक्ति की आवश्यकता है? क्या आप शायद अपने स्वयं के सरल खोज कार्यों को कार्यान्वित कर सकते हैं जो 85kb से कम तारों की लिंक्ड सूचियों पर काम कर सकते हैं?

इसके अलावा, LOH विखंडन केवल समस्याओं का कारण बनता है यदि आप लंबे समय तक बड़े ऑब्जेक्ट संदर्भों पर ध्यान देते हैं। यदि आप लगातार उन्हें बना रहे हैं और नष्ट कर रहे हैं, तो LOH नहीं बढ़ना चाहिए।

एफडब्ल्यूआईडब्लू, मैंने RedGate ANTS memory profiler को LOH में ऑब्जेक्ट्स को ट्रैक करने और विखंडन के स्तर को ट्रैक करने में बहुत अच्छा लगाया है।

+0

"LOH विखंडन केवल मुद्दों का कारण बनता है यदि आप लंबी अवधि के लिए बड़े ऑब्जेक्ट संदर्भों को धारण करते हैं" AFAIK यह सही नहीं है, 85KB से बड़ा कुछ भी LOH में स्थित होगा, चाहे वे कितने समय तक हों। मैं एएनटीएस प्रोफाइलर का उपयोग कर रहा हूं, वास्तव में यह बहुत अच्छा है। –

+0

हां Regex –

+0

की पूरी शक्ति की आवश्यकता है क्षमा करें, मेरा मतलब है कि मैंने केवल एलओएच के साथ समस्याएं देखी हैं जब संदर्भ लंबे समय तक चल रहे हैं। आप सही हैं कि 85k से अधिक कुछ भी LOH में जाता है। बस इतना है कि मैं समझता हूं, क्या आपकी समस्या है कि आपके पास LOH में आपके तारों के बीच आवंटित अन्य दीर्घकालिक ऑब्जेक्ट्स हैं, जिससे आपके स्ट्रिंग आवंटन को LOH को आगे बढ़ाया जा सकता है जब तक आप स्मृति से बाहर नहीं जाते? – SimonC

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