【问题标题】:Python cStringIO take more time than StringIO in writing (performance of string methods)Python cStringIO 在写入时比 StringIO 花费更多时间(字符串方法的性能)
【发布时间】:2015-01-16 14:58:34
【问题描述】:

以我在 python 中分析字符串方法的方式,以便我可以使用最快的方法。 我有这段代码来测试文件、StringIO、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 文档网站说 cStringIOStringIO 快​​,但结果显示 StringIO 在连接方面的性能更好,为什么?

  2. 另一方面,从cStringIO 读取比StringIO 更快(其行为类似于文件),因为我读取文件的实现和cStringIO 在C 中,所以为什么要字符串连接慢吗?

  3. 有没有其他方法可以比这些方法更快地处理字符串?

【问题讨论】:

  • CPython 解释器执行的 Python 代码中的字符串连接经过高度优化,但这并不一定会延续到 cStringIO 模块中手动编写的 C 代码中。请参阅 PEP-8 的 Programming Recommendations 部分中的第一个项目符号。
  • 感谢您提到的链接非常有帮助。在我的分析程序中,对 String 的操作比 StringIO 花费更多,但我很好奇为什么 cStringIO 在连接字符串时比 StringIO 花费更多时间,尽管 cStringIO 是用 C 编写的

标签: python string cstringio


【解决方案1】:

StringIO 性能更好的原因在于它在幕后只是保留了所有已写入其中的字符串的列表,并且仅在必要时将它们组合起来。因此,写入操作就像将对象附加到列表一样简单。但是,cStringIO 模块没有这种奢侈,必须将每个字符串的数据复制到其缓冲区中,并在必要时调整其缓冲区大小(这在写入大量数据时会产生大量冗余的数据复制)。

由于您要编写大量较大的字符串,这意味着与cStringIO 相比,StringIO 要做的工作更少。当从您写入的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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-09-30
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多