2014-11-19 5 views
7

В моем пути к профилю строковых методов в python, чтобы я мог использовать самый быстрый. У меня есть этот код для проверки конкатенации строк в файлах, StringIO, StringIO и обычной строке.Python cStringIO занимает больше времени, чем StringIO в письменной форме (производительность строковых методов)

#!/usr/bin/env python 
#title   : pythonTiming.py 
#description  : Will be used to test timing function in python 
#author   : myusuf 
#date   : 19-11-2014 
#version   : 0 
#usage   :python pythonTiming.py 
#notes   : 
#python_version :2.6.6 
#============================================================================== 

import time 
import cStringIO 
import StringIO 

class Timer(object): 

    def __enter__(self): 
     self.start = time.time() 
     return self 

    def __exit__(self, *args): 
     self.end = time.time() 
     self.interval = self.end - self.start 

testbuf = """ Hello This is a General String that will be repreated 
This string will be written to a file , StringIO and a sregualr strin then see the best to handle string according to time 

""" * 1000 

MyFile = open("./testfile.txt" ,"wb+") 
MyStr = '' 
MyStrIo = StringIO.StringIO() 
MycStrIo = cStringIO.StringIO() 

def strWithFiles(): 
    global MyFile 
    print "writing string to file " 
    for index in range(1000): 
     MyFile.write(testbuf) 
    pass 

def strWithStringIO(): 
    global MyStrIo 
    print "writing string to StrinIO " 
    for index in range(1000): 
     MyStrIo.write(testbuf) 

def strWithStr(): 
    global MyStr 
    print "Writing String to STR " 
    for index in range(500): 
     MyStr = MyStr + testbuf 

def strWithCstr(): 
    global MycStrIo 
    print "writing String to Cstring" 
    for index in range(1000): 
     MycStrIo.write(testbuf) 

with Timer() as t: 
    strWithFiles() 
print('##Request took %.03f sec.' % t.interval) 

with Timer() as t:                     
    strWithStringIO() 
print('###Request took %.03f sec.' % t.interval) 

with Timer() as t:                     
    strWithCstr() 
print('####Request took %.03f sec.' % t.interval) 

with Timer() as t: 
    read1 = 'x' + MyFile.read(-1) 
print('file read ##Request took %.03f sec.' % t.interval) 

with Timer() as t: 
    read2 = 'x' + MyStrIo.read(-1) 
print('stringIo read ###Request took %.03f sec.' % t.interval) 

with Timer() as t: 
    read3 = 'x' + MycStrIo.read(-1) 
print('CString read ####Request took %.03f sec.' % t.interval) 




MyFile.close() 
  1. Хотя в документации на сайте Python говорит, что cStringIO быстрее, чем StringIO, но результаты говорят, что StringIO имеет лучшую производительность конкатенации, почему?

  2. С другой стороны, что, читая cStringIO быстрее, чем StringIO (его поведение аналогично файлу), как я прочитал выполнение файла и cStringIO в C, так почему конкатенация медленно?

  3. Есть ли другой способ справиться со строкой быстрее, чем эти методы?

+1

Объединение строк в коде Python, исполняемой интерпретатор CPython высоко оптимизировано, но это не обязательно переносится на вручную написанный код C в 'модуле cStringIO'. См. Первую марку в разделе [_Programming Recommend_] (https://www.python.org/dev/peps/pep-0008/#programming-recommendations) раздела PEP-8. – martineau

+0

Спасибо за указанную ссылку было очень полезно. В моей программе профилирования операции над String имеют большую стоимость, чем StringIO, но мне любопытно, почему cStringIO занимает больше времени, чем StringIO при конкатенации строки, хотя cStringIO написан на C –

ответ

11

Причина, по которой StringIO выполняет лучше за кулисами он просто хранит список всех строк, которые были написаны для него, и только объединяет их в случае необходимости. Таким образом, операция записи так же просто, как добавление объекта в список. Однако модуль cStringIO не обладает этой роскошью и должен копировать данные каждой строки в свой буфер, изменяя размер своего буфера по мере необходимости (что создает много избыточное копирование данных при записи больших объемов данных).

Поскольку вы пишете много больших строк, это означает, что для StringIO меньше работы, чем cStringIO. При чтении с объекта StringIO, на который вы написали, он может выбрать количество копий, необходимое для вычисления суммы длин строк, написанных для него, предварительно распределяя буфер такого размера.

Однако StringIO не является самым быстрым способом соединения ряда строк. Это связано с тем, что он обеспечивает дополнительную функциональность (поиск различных частей буфера и запись данных там). Если эта функциональность не нужна, все, что вы хотите сделать, это объединение строк списка вместе, тогда str.join - это самый быстрый способ сделать это.

joined_string = "".join(testbuf for index in range(1000)) 
# or building the list of strings to join separately 
strings = [] 
for i in range(1000): 
    strings.append(testbuf) 
joined_string = "".join(strings) 

 Смежные вопросы

  • Нет связанных вопросов^_^