2012-10-09 18 views
13

मैंने re.match और re.search की तुलना timeit मॉड्यूल का उपयोग करने की तुलना करने की कोशिश की और मुझे पता चला कि स्ट्रिंग की शुरुआत में जब स्ट्रिंग मैं खोजना चाहता हूं तो मिलान खोज से बेहतर था।re.match बनाम re.search प्रदर्शन अंतर

>>> s1 = ''' 
... import re 
... re.search(r'hello','helloab'*100000) 
... ''' 
>>> timeit.timeit(stmt=s1,number=10000) 
32.12064480781555 


>>> s = ''' 
... import re 
... re.match(r'hello','helloab'*100000) 
... ''' 
>>> timeit.timeit(stmt=s,number=10000) 
30.9136700630188 

अब, मुझे पता है कि मैच स्ट्रिंग की शुरुआत में पैटर्न के लिए लग रहा है और एक ऑब्जेक्ट प्रदान करता है, तो पाया हूँ, लेकिन क्या मैं सोच रहा हूँ कि कैसे खोज काम करता है।

क्या स्ट्रिंग शुरू होने में स्ट्रिंग मिलने के बाद कोई अतिरिक्त मिलान करता है जो इसे धीमा कर देता है?

अद्यतन

@ दाऊद Robinsons कोड इस्तेमाल करने के बाद मैं उससे simlar परिणाम मिला है।

>>> print timeit.timeit(stmt="r.match('hello')", 
...    setup="import re; s = 'helloab'*100000; r = re.compile('hello')", 
...    number = 10000000) 
49.9567620754 
>>> print timeit.timeit(stmt="r.search('hello')", 
...    setup="import re; s = 'helloab'*100000; r = re.compile('hello')", 
...    number = 10000000) 
35.6694438457 

तो, अद्यतन सवाल अब क्यों search बाहर प्रदर्शन कर रहा है match है?

+7

आपको वास्तव में 'सेटअप' पैरामीटर में 'टाइमिट' में टेस्ट स्ट्रिंग और रेगेक्स ऑब्जेक्ट बनाना चाहिए ताकि आप केवल मैच/खोज को माप सकें। और 10 से अधिक पुनरावृत्तियों को करें। – interjay

+0

@interjay: इसे '10000' तक बढ़ा दिया गया। 'संख्या = 100000' का प्रयास किया लेकिन मेरी नेटबुक पर यह बहुत अधिक समय ले रहा था। – RanRag

+2

... लेकिन आपने अन्य चीजों को नहीं किया जो मैंने कहा था, इसलिए आप अपने प्रश्न के लिए महत्वपूर्ण कुछ भी माप नहीं रहे हैं (अधिकांश समय स्ट्रिंग का निर्माण करने में व्यतीत होता है)। – interjay

उत्तर

6

मेरी मशीन (मैक ओएस 10.7.3, 1.7 गीगाहर्ट्ज इंटेल कोर i5 पर पायथन 2.7.3), स्ट्रिंग निर्माण डालने, फिर से आयात करने और सेटअप में रेगेक्स संकलन करने और 10 के बजाय 10000000 पुनरावृत्तियों को करने पर "क्यों खोज मैच बाहर प्रदर्शन कर रहा है तो, अद्यतन सवाल अब है?"

import timeit 

print timeit.timeit(stmt="r.match(s)", 
      setup="import re; s = 'helloab'*100000; r = re.compile('hello')", 
      number = 10000000) 
# 6.43165612221 
print timeit.timeit(stmt="r.search(s)", 
      setup="import re; s = 'helloab'*100000; r = re.compile('hello')", 
      number = 10000000) 
# 3.85176897049 
+0

अब, दिलचस्प है। – RanRag

+1

मैं इस परिणाम की पुष्टि करता हूं। (ओएस एक्स 10.5.8, पायथन 2.7.3) मुझे लगता है कि 'खोज' लगभग 25% तेज है। – mgilson

+0

जैसा कि संपादन में उल्लेख किया गया है, अगर सेटअप सेटअप में रेगेक्स संकलन किया जाता है तो मुझे अंतर बढ़ता है। –

10

:, मैं विपरीत लगता है

इस विशेष उदाहरण हैं जहां एक शाब्दिक स्ट्रिंग एक regex पैटर्न के बजाय प्रयोग किया जाता है, वास्तव में re.search डिफ़ॉल्ट CPython कार्यान्वयन (मैं पायथन के अन्य रूपों में यह परीक्षण नहीं किया) के लिए re.match की तुलना में थोड़ा तेज है।

>>> print timeit.timeit(stmt="r.match(s)", 
...    setup="import re; s = 'helloab'*100000; r = re.compile('hello')", 
...    number = 10000000) 
3.29107403755 
>>> print timeit.timeit(stmt="r.search(s)", 
...    setup="import re; s = 'helloab'*100000; r = re.compile('hello')", 
...    number = 10000000) 
2.39184308052 

C code behind those modules में देख रहे हैं, ऐसा लगता है खोज कोड एक अनुकूलन to quickly match patterns prefixed with a string lateral में निर्माण किया है। उपर्युक्त उदाहरण में, संपूर्ण पैटर्न एक शाब्दिक स्ट्रिंग है जिसमें कोई रेगेक्स पैटर्न नहीं है और इसलिए यह अनुकूलित दिनचर्या पूरे पैटर्न से मेल खाने के लिए उपयोग किया जाता है।

सूचना कैसे प्रदर्शन खराब हो के रूप में शाब्दिक स्ट्रिंग उपसर्ग कम हो जाता है एक बार हम regex प्रतीकों का परिचय और,:

>>> print timeit.timeit(stmt="r.search(s)", 
...    setup="import re; s = 'helloab'*100000; r = re.compile('hell.')", 
...    number = 10000000) 

3.20765399933 
>>> 
>>> print timeit.timeit(stmt="r.search(s)", 
...    setup="import re; s = 'helloab'*100000; r = re.compile('hel.o')", 
...    number = 10000000) 
3.31512498856 
>>> print timeit.timeit(stmt="r.search(s)", 
...    setup="import re; s = 'helloab'*100000; r = re.compile('he.lo')", 
...    number = 10000000) 
3.31983995438 
>>> print timeit.timeit(stmt="r.search(s)", 
...    setup="import re; s = 'helloab'*100000; r = re.compile('h.llo')", 
...    number = 10000000) 
3.39261603355 

पैटर्न है कि regex पैटर्न होते हैं के भाग के लिए, SRE_MATCH मैचों निर्धारित करने के लिए प्रयोग किया जाता है। यह अनिवार्य रूप से re.match के पीछे एक ही कोड है।

नोट करें कि परिणाम कैसे बंद होते हैं (re.match थोड़ा तेज़ी से) यदि पैटर्न एक शाब्दिक स्ट्रिंग के बजाय रेगेक्स पैटर्न के साथ शुरू होता है।

>>> print timeit.timeit(stmt="r.match(s)", 
...    setup="import re; s = 'helloab'*100000; r = re.compile('.ello')", 
...    number = 10000000) 
3.22782492638 
>>> print timeit.timeit(stmt="r.search(s)", 
...    setup="import re; s = 'helloab'*100000; r = re.compile('.ello')", 
...    number = 10000000) 
3.31773591042 

दूसरे शब्दों में, इस तथ्य search और match विभिन्न प्रयोजनों है कि अनदेखी, re.searchre.match की तुलना में तेजी केवल जब पैटर्न एक शाब्दिक स्ट्रिंग है।

बेशक, यदि आप शाब्दिक तारों के साथ काम कर रहे हैं, तो आप इसके बजाय स्ट्रिंग ऑपरेशंस का उपयोग करना बेहतर हो सकते हैं।

>>> # Detecting exact matches 
>>> print timeit.timeit(stmt="s == r", 
...    setup="s = 'helloab'*100000; r = 'hello'", 
...    number = 10000000) 
0.339027881622 

>>> # Determine if string contains another string 
>>> print timeit.timeit(stmt="s in r", 
...    setup="s = 'helloab'*100000; r = 'hello'", 
...    number = 10000000) 
0.479326963425 


>>> # detecting prefix 
>>> print timeit.timeit(stmt="s.startswith(r)", 
...    setup="s = 'helloab'*100000; r = 'hello'", 
...    number = 10000000) 
1.49393510818 
>>> print timeit.timeit(stmt="s[:len(r)] == r", 
...    setup="s = 'helloab'*100000; r = 'hello'", 
...    number = 10000000) 
1.21005606651 
+0

शानदार अनुसंधान और प्रयोग। विशेष रूप से स्रोत के लिंक शामिल करने के लिए धन्यवाद। – pswaminathan

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