【发布时间】:2011-06-25 02:21:52
【问题描述】:
我已经分析了一些我使用 cProfile 继承的遗留代码。我已经做出了很多有用的更改(比如使用 simplejson 的 C 扩展!)。
基本上,此脚本将数据从一个系统导出到 ASCII 固定宽度文件。每一行都是一条记录,它有很多值。每行有 7158 个字符,包含大量空格。总记录数为 150 万条记录。每行一次生成一个,需要一段时间(每秒 5-10 行)。
在生成每一行时,它会尽可能简单地写入磁盘。分析表明,大约 19-20% 的总时间花费在 file.write() 上。对于 1,500 行的测试用例,需要 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 = []
我的第二个想法是使用另一个线程,但这让我想死在里面。
【问题讨论】:
-
应用的瓶颈是什么?
-
我以为我很清楚。它花费 20% 的时间一次写入磁盘一行。
-
那么,进行更改和配置文件吗?预计它不会产生什么影响,因为文件 I/O 通常是行缓冲的......或者我认为是这样。
-
线程不会有帮助。你怎么这么潮。我的意思是我知道勒布朗詹姆斯“永远不会忘记刷新”,但是你每次写到标准输出时都需要这样做吗?
-
@David,刷新是为了他的标准输出,而不是有问题的文件。
标签: python performance file-io