2010-11-30 17 views
5

में तारों में वर्ण प्रतिस्थापन मैं स्ट्रिंग में वर्णों को कितनी तेज़ी से बदल सकता हूं?वीबीएनईटी

तो इस प्रश्न पर पृष्ठभूमि यह है: हम अनुप्रयोगों है कि एक दूसरे के साथ और सॉकेट के माध्यम से ग्राहकों की अनुप्रयोगों के साथ संवाद की एक जोड़ी है। इन सॉकेट संदेशों में गैर-प्रिंट करने योग्य वर्ण होते हैं (उदाहरण के लिए chr (0)) जिन्हें पूर्व निर्धारित स्ट्रिंग (जैसे "{Nul}"} से प्रतिस्थापित करने की आवश्यकता होती है, क्योंकि सॉकेट संदेश लॉग फ़ाइल में रखे जाते हैं। एक तरफ नोट पर, नहीं हर लॉग संदेश पात्रों की जगह है करने के लिए वर्तमान पद्धति हम इस्तेमाल किया ... पर की आवश्यकता होगी।

अब मैं this MSDN link जो मैं इस साइट से एक अलग पोस्ट से मिला से इस छोटे से साहसिक पढ़ने पर शुरू कर दिया।

दिन की शुरुआत ... जैसे सभी संभव प्रतिस्थापन के लिए जाँच करने के लिए StringBuilder उपयोग कर रहा था ...

Public Function ReplaceSB(ByVal p_Message As String) As String 
     Dim sb As New System.Text.StringBuilder(p_Message) 

     sb.Replace(Chr(0), "{NUL}") 
     sb.Replace(Chr(1), "{SOH}") 

     Return sb.ToString 
    End Function 

अब ब्लॉग पोस्ट स्ट्रिंगबिल्डर को छोड़कर स्ट्रिंग.रेप्लेस का उपयोग करके इंगित करता है कि तेजी से परिणाम मिलते हैं। (वास्तव में, StringBuilder का उपयोग कर दिन भर ऐसा करने का सबसे धीमी तरीका था।)

p_Message = p_Message.Replace(Chr(0), "{NUL}") 
    p_Message = p_Message.Replace(Chr(1), "{SOH}") 

यह जानते हुए कि नहीं हर संदेश इस प्रक्रिया को मैंने सोचा कि यह नहीं करने के लिए समय की बचत होगी उन संदेशों को संसाधित करने के लिए के माध्यम से जाने की जरूरत है कि बाहर छोड़ा जा सकता है। इसलिए नियमित अभिव्यक्तियों का उपयोग करके मैंने पहली बार स्ट्रिंग की खोज की और फिर निर्धारित किया कि इसे संसाधित करने की आवश्यकता है या नहीं। यह string.replace का उपयोग करने के समान था, मूल रूप से सभी तारों को संसाधित करने के समय को बचाने से धोना, लेकिन नियमित अभिव्यक्तियों के साथ उन सभी को जांचने से समय खोना।

तो यह कुछ सरणियों कि पुराने और नए के साथ अपने अनुक्रमित मिलान और का उपयोग करें कि संदेश संसाधित करने का उपयोग कर की कोशिश करने का सुझाव दिया गया था। तो यह कुछ इस तरह होगा ...

Private chrArray() As Char = {Chr(0), Chr(1)} 
Private strArray() As String = {"{NUL}", "{SOH}"} 

Public Function TestReplace(ByVal p_Message As String) As String 
    Dim i As Integer 

    For i = 0 To ((chrArray.Length) - 1) 
     If p_Message.Contains(chrArray(i).ToString) Then 
      p_Message = p_Message.Replace(chrArray(i), strArray(i)) 
     End If 
    Next 

    Return p_Message 
End Function 

यह अब तक का सबसे तेज़ तरीका मैं इन संदेशों को संसाधित करने के लिए मिल गया है किया गया है। मैंने इस बारे में जाने के कई अन्य तरीकों की कोशिश की है, साथ ही आने वाली स्ट्रिंग को एक वर्ण सरणी में परिवर्तित करना और साथ ही साथ chrArray की बजाय स्ट्रिंग के माध्यम से लूप करने की कोशिश कर रहा है।

तो मेरा प्रश्न यह है कि: क्या मैं इसे अभी तक तेज कर सकता हूं? मैं क्या खो रहा हूँ?

+0

आप सी # उपयोग करने का विकल्प है, तो आप असुरक्षित कोड के साथ एक बुराई तेजी से समारोह में लिखने के लिए सक्षम हो सकता है। – Juliet

+0

मुझे आश्चर्य हुआ कि क्या यह संभव होगा, लेकिन जल्द ही उस विकल्प को गिनती है क्योंकि मुझे पैरामीटर के साथ काम करने के लिए दिया गया था ... ओह अच्छी तरह से – Tim

उत्तर

1

आप कुछ लुकअप को कम करके थोड़ा और गति निचोड़ने में सक्षम हो सकते हैं। उदाहरण के लिए इस लें:

If p_Message.Contains(chrArray(i).ToString) Then 

.Contains विधि हे (एन) है। सबसे बुरे मामले में, आप बिना किसी चीज के पूरे स्ट्रिंग में सभी वर्णों को पार करने जा रहे हैं, इसलिए आप अपने सरणी में प्रत्येक वर्ण के लिए कम से कम एक बार ट्रैवर्स करने की उम्मीद करते हैं, इसलिए इसकी ओ (एनएम) जहां n की लंबाई है आपकी स्ट्रिंग और एम उन वर्णों की संख्या है जिन्हें आप बदल रहे हैं।

आप थोड़ा बेहतर प्रदर्शन कर रही हो सकती है निम्नलिखित (मेरी वीबी फू जंग लगी है, का परीक्षण नहीं किया गया है;)):

Private Function WriteToCharList(s as String, dest as List(Of Char)) 
    for each c as Char in s 
     dest.Add(c) 
    Next 
End Function 

Public Function TestReplace(ByVal p_Message As String) As String 
    Dim chars as new List(Of Char)(p_Message.Length) 

    For each c as Char in p_Message 
     Select Case c 
      Case Chr(0): WriteToCharList("{NUL}", chars) 
      Case Chr(1): WriteToCharList("{SOH}", chars) 
      Case Else: chars.Add(c); 
     End Select 
    Next 

    Return New String(chars) 
End Function 

यह वर्ण p_Message में अधिक से अधिक दो बार (एक बार traversing के लिए पार किए जाने की , एक बार जब स्ट्रिंग कन्स्ट्रक्टर चार सरणी की प्रतिलिपि बनाता है), यह फ़ंक्शन ओ (एन) बनाते हैं।

+1

ध्यान दें कि मैं 'वर्ण' सूची के आकार को आरंभ कर रहा हूं। 'सूची ' संग्रह मूल रूप से एक सरणी के चारों ओर एक रैपर होता है, और यदि आप सरणी से अधिक आइटम जोड़ सकते हैं, तो यह आकार को दोहराए जाने के लिए सरणी का आकार बदलता है - इसलिए एक सिंगल char जोड़ना सबसे खराब मामला ओ (एन), औसत है मामला ओ (1)।यदि आप अपने पास Chr (0) और Chr (1) वर्णों की संख्या का आकलन कर सकते हैं, या केवल एक बड़ा पर्याप्त बफर आवंटित कर सकते हैं, तो आप कभी-कभी सरणी आकार बदलने से प्रदर्शन को थोड़ा बेहतर बना सकते हैं जब आप जो वर्ण जोड़ रहे हैं आपके चार सरणी की लंबाई से अधिक है। – Juliet

+0

धन्यवाद जूलियट। मैंने हर जवाब एक या दो परीक्षण दिया और यह सबसे तेज़ के रूप में आया। खैर अंतिम समाधान बिल्कुल इस तरह नहीं था, मूल विचार अभी भी वही है। मैं थोड़ा आश्चर्यचकित था, किसी कारण से मैंने नहीं सोचा था कि चयन का मामला तेज़ होगा, लेकिन यह है। – Tim

0

StringBuilder .NET में सबसे तेज़ Replace() फ़ंक्शन प्रदान करता है।

+0

स्ट्रिंगबिल्डर का प्रतिस्थापन() फ़ंक्शन सबसे धीमा था जिसे मैंने पूरे दिन कोशिश की थी। 240 लॉग संदेशों के माध्यम से प्रसंस्करण करते समय स्ट्रिंगबिल्डर मेरे ओपी से संदेशों को संसाधित करने के आखिरी तरीके से लगभग 1.8 मिलीसेकंड धीमा था। – Tim

+0

"यह निर्भर करता है" यहां सही जवाब है। आप वास्तव में गारंटी नहीं दे सकते कि वास्तव में प्रोफाइलिंग के बिना स्ट्रिंगबिल्डर तेजी से है। – Juliet

0

यहाँ सामान्य कुछ नोट:

  1. आप एक सादे .IndexOf() या .Contains() खोज का उपयोग करके खोज समारोह पर सुधार करने के लिए जब से तुम केवल एकल वर्ण के लिए देख रहे हो सकता है।
  2. आप (नोट प्रक्रिया में) सीधे अपने समारोह से StringBuilder वस्तु लौटने और अन्य कार्यों है कि इनपुट के रूप में stringbuilders या .ToString (बुला स्वीकार के लिए भार के उपलब्ध कराने के द्वारा अपने कुल प्रवाह क्षमता में सुधार करने के लिए कहीं पर बाद में सक्षम हो सकता है: आप भी कर सकते हैं वस्तुओं है कि पहले से ही तार कर रहे हैं)
  3. पर .ToString() फोन आप निश्चित रूप से धाराओं रखना है कि श्रृंखला को पारित कर दिया हो रही के रूप में सब कुछ का इलाज करने के लिए जारी आगे श्रृंखला को आगे एक StringReader/TextReader का उपयोग करके प्रदर्शन/throughput सुधार करने में सक्षम होना चाहिए ।

आप अपने अंतिम विधि इस तरह से संशोधित कर सकते हैं कम से कम:

Public Function TestReplace(ByVal p_Message As String) As String 
    Static chrArray() As Char = {ChrW(0), ChrW(1)} 
    Static strArray() As String = {"{NUL}", "{SOH}"} 

    Dim rdr As New StringReader(p_Message) 
    Dim result As New StringWriter() 

    Dim i As Integer 
    While (i = rdr.Read()) <> -1 
     Dim c As Char = ChrW(i) 
     Dim index As Integer = Array.IndexOf(chrArray, c) 
     If index >= 0 Then result.Write(strArray(index)) Else result.Write(c) 
    End While 

    Return result.ToString() 
End Function 

ध्यान रखें कि आपके मानक बहुत तार आप इसे फेंक रहे हैं के प्रकार पर निर्भर करेगा, इसलिए यह सुनिश्चित करें कि सबसे प्रतिनिधि नमूना का उपयोग (और यह एक अच्छा आकार का नमूना होना चाहिए) संभव है।

+0

मैंने किसी भी परिणाम प्राप्त किए बिना IndexOf() और .Contains() का उपयोग करने के विभिन्न तरीकों के साथ खेला, आमतौर पर एक मिलीसेकंड धीमी गति के दसवें या दो। मैं आपके नंबर 2 और 3 के साथ कुछ और परीक्षण करने जा रहा हूं ... मैं परिणाम – Tim

+0

@Tim पोस्ट करूंगा - मेरा अद्यतन उत्तर –

+0

देखें, मैं प्रत्येक परीक्षण के लिए 240 कच्चे लॉग संदेशों की एक सूची का उपयोग कर रहा हूं। मैं इस सेट को प्रश्न में फ़ंक्शन के लिए औसत कार्य भार से भारी के आधार पर चुनता हूं। प्रतिस्थापन करने वाले फ़ंक्शन को छोड़कर प्रत्येक परीक्षण में सब कुछ ठीक वही है। – Tim

0

इस example पर एक नज़र डालें। इसमें दो विधियों की तुलना में कुछ बेंचमार्क आंकड़े हैं।

+0

दिलचस्प पढ़ा, लेकिन मैंने जो परिणाम देखा है, उसके विपरीत हैं। स्ट्रिंगबिल्डर, कम से कम मेरे परीक्षण में, धीमे विकल्पों में से एक रहा है। – Tim

0

यह भी तेजी से किया जाना चाहिए:

Private Shared strList As New Dictionary(Of Char, String) 

    Shared Sub New() 
     strList.Add(Chr(0), "{NUL}") 
     strList.Add(Chr(1), "{SOH}") 
    End Sub 

    Public Function TestReplace(ByVal p_Message As String) As String 
     For Each c As Char In strList.Keys 
      If p_Message.IndexOf(c) <> -1 Then 
       p_Message = p_Message.Replace(c, strList(c)) 
      End If 
     Next 

     Return p_Message 
    End Function 
+2

ध्यान दें कि बिगओ स्टैंडपॉइंट से सटीक होने पर, अभ्यास में यह केवल तब तेज़ होता है जब आपका शब्दकोश आकार थोड़ा बड़ा हो जाता है - कम से कम 10 तत्व या अधिक। –

+0

यह निश्चित रूप से तेज़ था। यह वास्तव में 240 कच्चे संदेशों के एक ही परीक्षण डेटा का उपयोग करते हुए लगभग 2 मिलीसेकंड काटता है, लेकिन यह सबसे तेज़ नहीं था कि मेरे सभी परीक्षणों में मुझे किस तरह आश्चर्य हुआ ... मदद के लिए धन्यवाद – Tim