Python 加快文件写入速度

Python 加快文件写入速度,python,performance,file-io,Python,Performance,File Io,我已经分析了一些用cProfile继承的遗留代码。我已经做了很多有帮助的更改(比如使用simplejson的C扩展!) 基本上,该脚本将数据从一个系统导出到ASCII固定宽度文件。每一行都是一条记录,它有许多值。每行7158个字符,包含大量空格。记录总数为150万条。每行一次生成一行,需要一段时间(每秒5-10行) 在生成每一行时,它都会尽可能简单地写入磁盘。分析表明大约有19-20%的总时间花在file.write()上。对于1500行的测试用例,这是20秒。我想减少这个数字 现在看来,下一个

我已经分析了一些用cProfile继承的遗留代码。我已经做了很多有帮助的更改(比如使用simplejson的C扩展!)

基本上,该脚本将数据从一个系统导出到ASCII固定宽度文件。每一行都是一条记录,它有许多值。每行7158个字符,包含大量空格。记录总数为150万条。每行一次生成一行,需要一段时间(每秒5-10行)

在生成每一行时,它都会尽可能简单地写入磁盘。分析表明大约有19-20%的总时间花在
file.write()上。对于1500行的测试用例,这是20秒。我想减少这个数字

现在看来,下一个胜利将是减少写入磁盘的时间。如果可能的话,我想减少。我可以在内存中保留一个记录缓存,但我不能等到最后才一次将其全部转储

fd = open(data_file, 'w')
for c, (recordid, values) in enumerate(generatevalues()):
        row = prep_row(recordid, values)
        fd.write(row)
        if c % 117 == 0:
                if limit > 0 and c >= limit:
                        break
                sys.stdout.write('\r%s @ %s' % (str(c + 1).rjust(7), datetime.now()))
                sys.stdout.flush()
我的第一个想法是在一个列表中保存一个记录缓存,然后分批将它们写出来。那会更快吗?比如:

rows = []
for c, (recordid, values) in enumerate(generatevalues()):
        rows.append(prep_row(recordid, values))
        if c % 117 == 0:
            fd.write('\n'.join(rows))
            rows = []

我的第二个想法是使用另一个线程,但这让我想死在里面。

实际上,你的问题不是
文件。write()
占用了你20%的时间。80%的时间你不在
文件中。write()

写入磁盘的速度很慢。对此你真的无能为力。将内容写入磁盘只需花费大量时间。你几乎无法加快速度


你想要的是让I/O时间成为程序的最大部分,这样你的速度就受到硬盘速度的限制,而不是你的处理时间。理想情况是
file.write()
的使用率达到100%

您可以在python中执行,这可能会有所帮助。但我怀疑您在评测时犯了一些错误,因为20秒内的7k*1500大约是0.5 Mbytes/s。做一个测试,在测试中,你写的是相同长度的随机行,你会发现它比这快得多。

将写操作分为500组确实大大加快了写操作的速度。对于这个测试用例,在I/O中单独写入行需要21.051秒,而在117个批次中写入相同数量的行需要5.685秒。500个批次总共只花了0.266秒

应用程序的瓶颈是什么?我想我很清楚。它花了20%的时间一次一行写入磁盘。那么,进行更改并对其进行分析?由于文件I/O通常是行缓冲的,所以预期效果很小。。。或者我是这么想的。线程化不会有什么帮助。你为什么脸红这么多。我的意思是,我知道勒布朗·詹姆斯“永远不会忘记冲刷”,但是每次你给STDUT写信都需要这样做吗?@戴维,FLASH是针对他的STDUT,而不是文件。+ 1,通常我同意你的观点。然而,在这种情况下,我用来生成数据的外部过程非常慢,我希望尽可能地最小化其他一切。我想我应该在几秒钟内谈一谈,然后集中精力解决这个问题。将进行编辑以澄清秒数。更新以指定写入1500条记录需要20秒。我真的很关心这个数字,我只是用百分比来证明它确实值得优化。@chmullig,有多少%的人在等待外部进程?~53%的人在等待外部进程。另外约3%用于某些头类型函数。14%用于simplejson加载()20%用于IO。所以只有10%是我的代码。@chmullig,这里有些不对劲。写作不可能花那么长时间。看看python程序是否可以更快地将其他随机字符串写入磁盘。现在,您可以为文件写入添加线程,以更好地执行asynhronus写入-只需输出到stdout,通过管道将其传输到文件,并让操作系统为您执行缓冲和批写入操作。:)@LesterCheung,你能详细说明一下吗?@blindguy喜欢“python yourprog.py | buffer>out”,但我认为批处理输出在这里仍然有用。与他的方法相比,性能如何?操作系统的缓冲速度也一样快吗?