2015-11-08 7 views
7

क्यों परवाह नहीं करता है रेगेक्स पर इनपुट लंबाई प्रदर्शन को प्रभावित नहीं करती है और यह कैसे संभव है?रेगेक्स स्ट्रिंग लम्बाई

जेनरेट की गई स्ट्रिंग इस तरह है: 128 यादृच्छिक वर्ण। फिर कोष्ठक के अंदर दो संख्याएं। और यह कई बार दोहराया जाता है।

128 radnom characters....(-2435346|45436) 128 radnom characters....(-32525562|-325346) 

रेगेक्स को सभी संख्याएं ब्रांड्स के अंदर मिलती हैं। यहां पैटर्न है।

\(([-+]?\d+\|[-+]?\d+)\) 

तो मैचों होगा की तरह

-2435346|45436 
-32525562|-325346 
etc... 

यहाँ कोड है कि बेंचमार्क करता है। इनपुट उत्पन्न होने के बाद मैं स्टॉप घड़ी शुरू करता हूं क्योंकि मैं केवल मिलान समय का मूल्यांकन करना चाहता हूं।

Random rand = new Random(); 
Func<string> getRandString = // generates 128 random characters. 
    () => Enumerable.Range(0, 128).Select(x => (char) rand.Next()).Aggregate("", (a, b) => a + b); 
Func<int> getRandInteger =() => rand.Next(); // generates random number. 
string format = "{0}({1}|{2})"; 

// Generate the big string. 
StringBuilder bigstr = new StringBuilder(); 
for (int i = 0; i < 100; i++) // repeat 100 times. 
{ 
    bigstr.Append(string.Format(format, getRandString(), getRandInteger(), getRandInteger())); 
} 
string input = bigstr.ToString(); 

Stopwatch stopwatch = Stopwatch.StartNew(); 
var matches = Regex.Matches(input, @"\(([-+]?\d+\|[-+]?\d+)\)"); 
stopwatch.Stop(); 
Console.WriteLine("Time Elapsed :\t{0}\nInputLength :\t{1}\nMatches Count :\t{2}", stopwatch.Elapsed, input.Length, matches.Count); 

यह मेरा कंसोल में उत्पादन अगर मैं पाश 10 बार दोहराने है।

Time Elapsed : 00:00:00.0004132 
InputLength : 1500 
Matches Count : 10 

अगर मैं पाश 1000 बार दोहराएँ।

Time Elapsed : 00:00:00.0004373 // seriously? 
InputLength : 149937 
Matches Count : 1000 

यदि मैं लूप 1000000 बार दोहराता हूं।

Time Elapsed : 00:00:00.0004900 // wtf? 
InputLength : 149964452 
Matches Count : 1000000 

स्क्रीनशॉट यदि आपको लगता है

enter image description here

इस आलसी मूल्यांकन किसी तरह का है न? यदि हां तो यह मैचों की गिनती कैसे दिखा सकता है? मैंने डीबगर के तहत यह कैसे किया और मैं मैचों को देख सकता था।

क्या मेरे रेगेक्स पैटर्न में कुछ विशिष्ट है जो इसे तेज़ बनाता है? लेकिन स्ट्रिंग लम्बाई प्रदर्शन को कैसे प्रभावित नहीं करती है? मैं समझ नहीं सकता

+0

कुछ भी विशेष here.Your regex इंजन स्ट्रिंग ट्रेवर्स और सभी कहती है कि आपके regex से मेल खाता बचत होगी है, और आप एक 1000 समय बड़ा स्ट्रिंग जो अब adays machines.Just के लिए एक बड़ी बात नहीं है पर बेंचमार्क हैं की कोशिश बहुत बड़ा तारया शायद आपका बेंचमारिक उचित नहीं है। – Kasramvd

+1

यदि आप .NET regex इंजन द्वारा उपयोग की जाने वाली स्ट्रिंग खोज एल्गोरिदम के बारे में कुछ विवरण देखना चाहते हैं तो आपको [मेरा यह जवाब] [http://stackoverflow.com/a/32618592/3764814) में रुचि हो सकती है। –

+1

उचित बेंचमार्किंग: https://andreyakinshin.gitbooks.io/performancebookdotnet/content/science/microbenchmarking.html –

उत्तर

9

ऐसा होने का एक कारण यह है कि matches.Count संपत्ति का मूल्यांकन आलसी है। जब आप अपना स्टॉपवॉच रोकते हैं, तो मैचर मिलान करने के लिए तैयार होता है, लेकिन इसे कुछ भी नहीं मिला है। केवल तभी जब आप matches.Count पर कॉल करते हैं तो यह काम करना शुरू कर देता है, लेकिन आपने तब तक समय बंद कर दिया है।

एक सरल समाधान कोड है कि आप समय के हिस्से में matches.Count कॉल स्थानांतरित करने के लिए है।

एक अन्य कारण यह है कि आप रीजिक्स को खाते में पार्स करने के लिए समय लेते हैं। यह एक अपेक्षाकृत महंगा ऑपरेशन है, ताकि आप बेहतर समय के लिए स्टॉपवॉच चालू करने से पहले यह करना चाहिए:, हालांकि

Regex testRegex = new Regex(@"\(([-+]?\d+\|[-+]?\d+)\)"); 
Stopwatch stopwatch = Stopwatch.StartNew(); 
var matches = testRegex.Matches(input); 
var matchesCount = matches.Count; 
stopwatch.Stop(); 
Console.WriteLine("Time Elapsed :\t{0}\nInputLength :\t{1}\nMatches Count :\t{2}", stopwatch.Elapsed, input.Length, matchesCount); 

अब 10 मैच बनाम 10,000 मैचों के लिए समय के विकास को काफी (00:00:00.0129844 बनाम 00:00:00.0843982) हो जाता है उतना बड़ा नहीं जितना कि इनपुट लंबाई में हजारों बार अंतर की उम्मीद हो सकती है।

+0

एलओएल, मैंने सोचा कि यह समय वास्तव में स्ट्रिंग उत्पन्न करने के लिए होता है। क्या एक बेवकूफ गलती है! मैंने डीबगर के तहत भी ऐसा किया लेकिन मैंने 'Regex.Matchches' के बाद ब्रेक पॉइंट डाला। फिर भी धन्यवाद! –

+1

@ एमकेज़ेमखरी यहां [मिलानकोलेक्शन' का कार्यान्वयन] है (http://reflector.webtropy.com/default.aspx/[email protected]/[email protected]/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/fx/ src/Regex/सिस्टम/पाठ/RegularExpressions/RegexMatchCollection @ सीएस/1305376/RegexMatchCollection @ सीएस)। आप कोड से देख सकते हैं कि 'GetMatch' विधि जो सभी कामों को आलसी कहा जाता है। – dasblinkenlight

+0

@dasblinkenlight आपके द्वारा प्रदान किया गया लिंक मेरे लिए काम नहीं करता है (वेबपृष्ठ खराब है और सभी कोड पृष्ठभूमि के समान रंग हैं), [यहां संदर्भ स्रोत में एक ही विधि का एक लिंक है] (http: // संदर्भ .microsoft.com/सिस्टम/regex/system/पाठ/regularexpressions/RegexMatchCollection.cs.html # 682620f47b442b05) –

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