【发布时间】:2017-01-16 11:23:57
【问题描述】:
我正在编写一个程序,它生成指定数量的句子,每个句子都写入一个文件。我一直在尝试针对 1000 万个或更多句子的案例优化代码。
我最近在我的开放调用中将缓冲区参数指定为 512MB,以提高写入性能,然而,我的代码实际上变慢了 3 秒。罪魁祸首是一个叫做{method 'close' of '_io.TextIOWrapper' objects}的东西。我认为这与文件关闭方法有关,但这是我第一次比较配置文件输出。
这是我以前的写入速度有多慢:
10000000 49.057 0.000 49.057 0.000 {method 'write' of '_io.TextIOWrapper' objects}
现在是这样的:
10000000 3.184 0.000 3.184 0.000 {method 'write' of '_io.TextIOWrapper' objects}
相当大的改进。
这是我以前的关闭方法:
3 4.003 1.334 4.003 1.334 {method 'close' of '_io.TextIOWrapper' objects}
这是我的新的:
1 62.668 62.668 62.668 62.668 {method 'close' of '_io.TextIOWrapper' objects}
这是我的代码:
def sentence_maker(nouns, verbs, number_of_sentences, file_name):
writer = open(file_name, "w", 536870912)
for num in range(number_of_sentences):
string = (choice(nouns) + " " + choice(verbs) + " " + choice(nouns))
writer.write(string + "\n")
writer.close()
为什么close() 这么慢?
注意:在程序的早期某处,我曾经有一些 close() 语句,因此在我的旧 close() 示例中使用了 ncalls = 3。我已确定这些对性能没有明显影响。
【问题讨论】:
-
请确保在发布 Python 代码时准确地复制缩进。严重缩进的 Python 代码是无稽之谈。
-
您是否尝试过使用
with open(<file_name>,'w') as fp:样式进行测试? -
通常最好使用
with而不是“正常”关闭文件。 -
由于
close也会刷新文件缓冲区尝试使用显式writer.flush()进行测量 -
@Bakuriu 是的......它需要 134 和几百万行才能使缓冲区溢出。我想性能开销来自维护缓冲区所需的内存分配/管理(特别是正如 chepner 所指出的 - 如果其中一些缓冲区最终被换出),以及单个大刷新最终会影响底层操作系统的事实系统缓冲区,仍然需要 N 次较小的刷新/同步。一般来说,任何大于物理驱动器块大小的东西都没有多大好处。
标签: python performance io