2012-07-18 7 views
9

मैं एक तनाव परीक्षण क्लाइंट का निर्माण कर रहा हूं जो सर्वर को हथियार देता है और ग्राहक के रूप में कई धागे का उपयोग करके प्रतिक्रियाओं का विश्लेषण करता है। मैं लगातार कचरा संग्रह (और/या इसकी कमी) द्वारा खुद को थ्रॉटल कर रहा हूं, और ज्यादातर मामलों में, यह स्ट्रिंग्स पर आता है कि मैं केवल उन्हें रेगेक्स या एक्सएमएल पार्सिंग रूटीन में पास करने के लिए तत्काल हूं।क्या किसी ने स्ट्रिंगबिल्डर या स्ट्रीम के आसपास रेगेक्स और/या एक्सएमएल पार्सर लागू किया है?

आप Regex वर्ग डिकंपाइल हैं, तो आप लेकिन वह आंतरिक, यह StringBuilders का उपयोग करता है लगभग सब कुछ करने देखेंगे, आप नहीं कर सकते पास यह एक स्ट्रिंग बिल्डर; यह उनको उपयोग करने से पहले निजी तरीकों से मददगार तरीके से नीचे उतरता है, इसलिए एक्सटेंशन विधियां इसे हल करने वाली नहीं हैं। यदि आप System.Xml.Linq में पार्सर से ऑब्जेक्ट ग्राफ़ प्राप्त करना चाहते हैं तो आप एक समान स्थिति में हैं।

यह पैडेंटिक ओवर-ऑप्टिमाइज़ेशन-इन-अग्रिम का मामला नहीं है। मैंने Regex replacements inside a StringBuilder प्रश्न और अन्य को देखा है। मैंने यह देखने के लिए भी अपना ऐप प्रोफाइल किया है कि छत कहाँ से आ रही है, और Regex.Replace() का उपयोग करके अब वास्तव में एक विधि श्रृंखला में महत्वपूर्ण ओवरहेड पेश कर रहा है जहां मैं प्रति घंटे लाखों अनुरोधों के साथ एक सर्वर को मारने की कोशिश कर रहा हूं और त्रुटियों के लिए XML प्रतिक्रियाओं की जांच कर रहा हूं और एम्बेडेड डायग्नोस्टिक कोड। मैं पहले से ही हर दूसरी अक्षमता से छुटकारा पा रहा हूं जो थ्रूपुट को थ्रॉटल कर रहा है, और मैंने स्टिंगबिल्डर को विस्तारित करने के लिए स्ट्रिंगबिल्डर को विस्तारित करके बहुत सारे रेगेक्स ओवरहेड को भी काट दिया है जब मुझे कैप्चर समूह या बैकरेफर की आवश्यकता नहीं होती है, लेकिन ऐसा लगता है कि किसी ने अब तक कस्टम स्ट्रिंगबिल्डर (या बेहतर अभी तक, स्ट्रीम) आधारित रेगेक्स और एक्सएमएल पार्सिंग उपयोगिता को लपेट लिया होगा।

ठीक है, तो rant over, लेकिन क्या मुझे यह खुद करना होगा?

अद्यतन: मुझे एक वर्कअराउंड मिला जो कई गीगाबाइट्स से कुछ सौ मेग्स तक चोटी मेमोरी खपत को कम करता है, इसलिए मैं इसे नीचे पोस्ट कर रहा हूं। मैं इसे एक उत्तर के रूप में नहीं जोड़ रहा हूं क्योंकि ए) मैं आमतौर पर ऐसा करने से नफरत करता हूं, और बी) मैं अभी भी यह जानना चाहता हूं कि कोई स्ट्रिंगबिल्डर को रीजिक्स (या इसके विपरीत) करने से पहले अनुकूलित करने के लिए समय लेता है या नहीं।

मेरे मामले में, मैं XmlReader का उपयोग नहीं कर सका क्योंकि धारा में प्रवेश करने वाली धारा में कुछ तत्वों में कुछ अमान्य द्विआधारी सामग्री शामिल है। एक्सएमएल को पार्स करने के लिए, मुझे उन तत्वों को खाली करना होगा। मैं पहले प्रतिस्थापन करने के लिए एक स्थिर संकलित रेगेक्स उदाहरण का उपयोग कर रहा था, और पागल की तरह यह उपभोग स्मृति (मैं ~ 300 10 केबी दस्तावेज़/सेक को संसाधित करने की कोशिश कर रहा हूं)। परिवर्तन यह है कि तेजी से खपत कम हो गया था:

  1. मैं काम IndexOf विधि के लिए इस StringBuilder Extensions article on CodeProject से कोड गयी।
  2. मैं एक (बहुत) कच्चे तेल की WildcardReplace विधि है कि एक वाइल्डकार्ड वर्ण की अनुमति देता है जोड़ा (* या?) मंगलाचरण प्रति
  3. मैं एक WildcardReplace() कॉल के साथ Regex उपयोग हमलावर तत्वों की सामग्री को खाली करने के लिए बदल दिया

यह बहुत ही सरल और परीक्षण है जहां तक ​​मेरे अपने उद्देश्यों की आवश्यकता होती है; मैं इसे और अधिक सुरुचिपूर्ण और शक्तिशाली बना देता, लेकिन यज्ञ और वह सब, और मैं जल्दी में हूं। यहां कोड है:

/// <summary> 
/// Performs basic wildcard find and replace on a string builder, observing one of two 
/// wildcard characters: * matches any number of characters, or ? matches a single character. 
/// Operates on only one wildcard per invocation; 2 or more wildcards in <paramref name="find"/> 
/// will cause an exception. 
/// All characters in <paramref name="replaceWith"/> are treated as literal parts of 
/// the replacement text. 
/// </summary> 
/// <param name="find"></param> 
/// <param name="replaceWith"></param> 
/// <returns></returns> 
public static StringBuilder WildcardReplace(this StringBuilder sb, string find, string replaceWith) { 
    if (find.Split(new char[] { '*' }).Length > 2 || find.Split(new char[] { '?' }).Length > 2 || (find.Contains("*") && find.Contains("?"))) { 
     throw new ArgumentException("Only one wildcard is supported, but more than one was supplied.", "find"); 
    } 
    // are we matching one character, or any number? 
    bool matchOneCharacter = find.Contains("?"); 
    string[] parts = matchOneCharacter ? 
     find.Split(new char[] { '?' }, StringSplitOptions.RemoveEmptyEntries) 
     : find.Split(new char[] { '*' }, StringSplitOptions.RemoveEmptyEntries); 
    int startItemIdx; 
    int endItemIdx; 
    int newStartIdx = 0; 
    int length; 
    while ((startItemIdx = sb.IndexOf(parts[0], newStartIdx)) > 0 
     && (endItemIdx = sb.IndexOf(parts[1], startItemIdx + parts[0].Length)) > 0) { 
     length = (endItemIdx + parts[1].Length) - startItemIdx; 
     newStartIdx = startItemIdx + replaceWith.Length; 
     // With "?" wildcard, find parameter length should equal the length of its match: 
     if (matchOneCharacter && length > find.Length) 
      break; 
     sb.Remove(startItemIdx, length); 
     sb.Insert(startItemIdx, replaceWith); 
    } 
    return sb; 
} 
+2

कच्चे डेटा को बचाने और बाद में इसका विश्लेषण करने के लिए यह आपके परिदृश्य में व्यवहार्य है? मैंने कुछ प्रकार के विश्लेषण को देखा है जो इस दृष्टिकोण को लेते हैं ... – Andre

+0

@ एंड्रे, हाँ, यह शायद एक अच्छा सुझाव है, मैंने अभी तक इसे दूर करने के लिए सभी तर्कों के कारण इसे टाल दिया है। वर्तमान रणनीति असीमित रूप से सब कुछ पार्स करना है, प्रतिक्रिया के बाहर आवश्यक वस्तु ग्राफ प्राप्त करें और बाद में गहन विश्लेषण के लिए मोंगो डीबी में फेंक दें। तो मुझे लगता है कि अगर मैं सबकुछ अपनाने का प्रयास नहीं करता हूं Regex एक आवंटित करने के लिए आवश्यक सब कुछ पर निर्भर करता है और अनुकूलित करता है। Resplace(), यह अगला सबसे अच्छा विकल्प है। अगर कोई प्री-रोलेड समाधान खांसी नहीं लेता है, तो मुझे लगता है कि मुझे यह निर्णय लेना होगा। –

+0

आपके द्वारा निर्दिष्ट किए गए दो अनुकूलन आपके नियमित अभिव्यक्तियों के लिए 'RegexOptions.Compiled' का उपयोग कर रहे हैं, और सर्वर कचरा कलेक्टर का उपयोग कर रहे हैं। क्या आपने उन दोनों को किया है? –

उत्तर

1

मोनो प्रोजेक्ट में switched the license for their core libraries to an MIT X11 license है।यदि आपको अपने विशेष एप्लिकेशन में प्रदर्शन के लिए अनुकूलित रेगेक्स लाइब्रेरी बनाने की आवश्यकता है, तो आपको के कार्यान्वयन Mono's से नवीनतम कोड से शुरू करने में सक्षम होना चाहिए।

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