Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么file.close()会减慢我的代码_Python_Performance_Io - Fatal编程技术网

Python 为什么file.close()会减慢我的代码

Python 为什么file.close()会减慢我的代码,python,performance,io,Python,Performance,Io,我正在编写一个程序,生成指定数量的句子,每个句子都写入一个文件。我一直在尝试优化1000万句以上的案例代码 最近,为了提高写性能,我在open调用中将buffer参数指定为512MB,但是,我的代码实际上慢了3秒。罪魁祸首是名为“\u io.TextIOWrapper”对象的{method'close}的东西。我认为这与file close方法有关,但这是我第一次比较概要文件输出 这就是我以前的写入速度有多慢: 10000000 49.057 0.000 49.057 0.0

我正在编写一个程序,生成指定数量的句子,每个句子都写入一个文件。我一直在尝试优化1000万句以上的案例代码

最近,为了提高写性能,我在open调用中将buffer参数指定为512MB,但是,我的代码实际上慢了3秒。罪魁祸首是名为“\u io.TextIOWrapper”对象的
{method'close}
的东西。我认为这与file close方法有关,但这是我第一次比较概要文件输出

这就是我以前的写入速度有多慢:

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将自动将其写入磁盘或在调用close()时将其写入磁盘。

写入磁盘的速度很慢,因此许多程序会将写入存储到大块中,然后一次全部写入。这称为缓冲,Python会在您打开文件时自动执行。当您写入文件时,实际上是在写入内存中的“缓冲区”。当它填满时,Python将自动将其写入磁盘或调用close()。

您明确选择使用一个巨大的缓冲区(536870912是刷新缓冲区之前缓冲的字节数,大约半GB内存)
close
包含对缓冲区中剩余内容的隐式
flush
,假设你写了很多东西,这意味着它需要全部写出来

您必须在某个时候为实际I/O付费;一个大的缓冲区使得
write
变得便宜(因为它实际上不执行任何I/O),但是一个如此大的缓冲区只是延迟痛苦,而不是避免痛苦。我怀疑任何超过1MB的缓冲区大小实际上会节省有意义的工作(并且限制可能更低);如果经常执行系统调用,则执行系统调用的成本很高,但如果每次调用所做的工作(实际的物理I/O)超过这两个调用一个数量级或更多,则每MB一次调用和每512 MB一次调用之间的差异就没有意义


作为比较,使用缓冲区的原因是,与常规函数调用()相比,系统调用具有较高的开销。CPython在I/O(释放和恢复GIL)中涉及一些额外的系统调用,因此系统调用
write
memcpy
的增量成本可能相差100-1000倍。但就现代CPU的开销而言,即使是2000个滴答声也在微秒范围内。但I/O本身要比这贵得多;写入10MB的数据可能需要十分之一秒左右的时间当I/O本身的成本以秒为单位时,通过使用较大的缓冲区大小在系统调用中节省几毫秒并不重要。而且如此大的缓冲区将开始引入缓存未命中(以及可能的页面错误),而较小的缓冲区可以避免这些情况。

您明确选择使用较大的缓冲区(536870912是刷新缓冲区之前缓冲的字节数,大约半GB的内存)。
close
包括对缓冲区中剩余内容的隐式
flush
,假设您写了很多,这意味着需要将其全部写出来

在某个时候,你必须为实际的I/O付费;一个大的缓冲区会使
write
变得便宜(因为它实际上不执行任何I/O),但是一个如此大的缓冲区只是推迟痛苦,而不是避免痛苦。我怀疑任何超过1MB的缓冲区都会实际节省有意义的工作(限制可能更低);如果经常执行系统调用,则执行系统调用的成本很高,但如果每次调用所做的工作(实际物理I/O)超过这两个调用一个数量级或更多,则每MB一次调用与每512 MB一次调用之间的差异就没有意义


为了进行比较,使用缓冲区的原因是,与常规函数调用()相比,系统调用具有较高的开销。CPython在I/O中涉及一些额外的系统调用(释放和恢复GIL)因此,系统调用
写入
的增量成本与
memcpy
的增量成本可能相差100-1000倍。但就现代CPU的开销而言,即使2000个滴答声也在微秒范围内。但I/O本身要比这贵得多;写入10 MB数据可能需要十分之一秒左右的时间。节省了几mil当I/O本身的成本以秒为单位时,使用更大的缓冲区大小进行系统调用的时间不重要。而且如此大的缓冲区将开始引入缓存未命中(以及可能的页面错误)这将避免使用较小的缓冲区。

请确保在发布Python代码时准确地复制缩进。缩进严重的Python代码是胡说八道。您是否尝试过使用带有打开(,'w')的
作为fp:
样式进行测试?通常最好使用带有
而不是“正常”关闭文件。由于
close
也会刷新文件缓冲区,请尝试使用显式
writer.flush()
@Bakuriu()进行测量。是的……要使缓冲区溢出需要134行和大约一百万行。我想性能开销来自维护缓冲区所需的内存分配/管理(特别是正如切普纳所指出的——如果某些缓冲区最终被交换掉的话),以及