2013-12-14 12 views
14

मैंने अभी इस स्क्रिप्ट को पायथन 3.3 के साथ चलाने की कोशिश की है। दुर्भाग्य से यह पाइथन 2.7 के मुकाबले धीमी गति से दोगुना है।पायथन 3.3 में इतना धीमा प्रिंट क्यों है और मैं इसे कैसे ठीक कर सकता हूं?

#!/usr/bin/env python 

from sys import stdin 

def main(): 
    for line in stdin: 
     try: 
      fields = line.split('"', 6) 
      print(fields[5]) 
     except: 
      pass 

if __name__ == '__main__': 
    main() 

यहाँ परिणाम हैं:

$ time zcat access.log.gz | python3 -m cProfile ./ua.py > /dev/null 

real 0m13.276s 
user 0m18.977s 
sys  0m0.484s 

$ time zcat access.log.gz | python2 -m cProfile ./ua.py > /dev/null 

real 0m6.139s 
user 0m11.693s 
sys  0m0.408s 

रूपरेखा से पता चलता अतिरिक्त समय प्रिंट में खर्च है कि:

$ zcat access.log.gz | python3 -m cProfile ./ua.py | tail -15 
    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 0.000 0.000 <frozen importlib._bootstrap>:1594(_handle_fromlist) 
    196806 0.234 0.000 0.545 0.000 codecs.py:298(decode) 
     1 0.000 0.000 13.598 13.598 ua.py:3(<module>) 
     1 4.838 4.838 13.598 13.598 ua.py:6(main) 
     1 0.000 0.000 13.598 13.598 {built-in method exec} 
     1 0.000 0.000 0.000 0.000 {built-in method hasattr} 
    4300456 4.726 0.000 4.726 0.000 {built-in method print} 
    196806 0.312 0.000 0.312 0.000 {built-in method utf_8_decode} 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 
    4300456 3.489 0.000 3.489 0.000 {method 'split' of 'str' objects} 

$ zcat access.log.gz | python2 -m cProfile ./ua.py | tail -10 
    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 6.573 6.573 ua.py:3(<module>) 
     1 3.894 3.894 6.573 6.573 ua.py:6(main) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 
    4300456 2.680 0.000 2.680 0.000 {method 'split' of 'str' objects} 

मैं इस भूमि के ऊपर कैसे बच सकते हैं? क्या यूटीएफ -8 के साथ कुछ करना है?

+3

ठीक है, 'प्रिंट' अब python3 में कोई कथन नहीं है, इसलिए कुछ ओवरहेड की उम्मीद है। यह संभवतः 'sys.stdout.write' का उपयोग करके कम किया जा सकता है - या इससे भी बेहतर, पहले अपने स्ट्रिंग्स की एक सूची बनाकर और फिर' sys.stdout.writelines' का उपयोग करके, मान लें कि स्मृति कोई मुद्दा नहीं है। दोनों मामलों में, आपको 'प्रिंट' द्वारा बनाए गए न्यूलाइन को जोड़ना होगा। – l4mpi

उत्तर

12

पायथन 3 डीकोड डेटा stdin से पढ़ता है और stdout पर फिर से एन्कोड करता है; यह print() फ़ंक्शन इतना नहीं है जो यूनिकोड-टू-बाइट रूपांतरण और इसके विपरीत के रूप में धीमा है।

अपने मामले में आप शायद इसे बाईपास करना चाहते हैं और केवल बाइट से निपटना चाहते हैं; आप .buffer attribute के माध्यम से अंतर्निहित BufferedIOBase कार्यान्वयन पहुँच सकते हैं:

from sys import stdin, stdout 

try: 
    bytes_stdin, bytes_stdout = stdin.buffer, stdout.buffer 
except AttributeError: 
    bytes_stdin, bytes_stdout = stdin, stdout 

def main(): 
    for line in bytes_stdin: 
     try: 
      fields = line.split(b'"', 6) 
      bytes_stdout.write(fields[5] + b'\n') 
     except IndexError: 
      pass 

if __name__ == '__main__': 
    main() 

आप करेंगे अब stdout.write()print() रूप stdoutTextIOBase कार्यान्वयन के लिए लिख पर जोर उपयोग करना होगा।

ध्यान दें कि .split() अब एक बाइट्स शाब्दिक b'"' का उपयोग करता है और एक बाइट-शाब्दिक b'\n' रूप में अच्छी तरह (सामान्य रूप से print() द्वारा ध्यान रखा की जाएगी जो) हम लिखें।

उपर्युक्त पायथन 2.6 और ऊपर के साथ संगत है। पायथन 2.5 b उपसर्ग का समर्थन नहीं करता है।

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