我正在研究python3.6.0中的文件I/O性能。给出由3个测试组成的脚本:
#!python3
import random, string, time
strs = ''.join(random.choice(string.ascii_lowercase) for i in range(1000000))
strb = bytes(strs, 'latin-1')
inf = open('bench.txt', 'w+b')
inf.write(strb)
for t in range(3):
inf.seek(0)
inf.read(8191)
for t in range(3):
inf.seek(0)
inf.read(8192)
for t in range(3):
inf.seek(0)
inf.read(8193)
inf.close()
Procmon看到以下操作正在发生(我的注释是hashtag行):
^{pr2}$首先,很明显python将以8KiB的倍数读取文件。在
我怀疑python实现了一个缓存缓冲区,该缓冲区存储最后读取的8KiB块,如果您试图在同一个8KiB范围内连续多次只读,则只会返回并裁剪它。在
有人能确认python实现了这个机制吗?在
如果是这样的话,这意味着如果不以某种方式手动使缓存失效,python就无法检测到外部应用程序对该块所做的更改。对吗?也许有一种方法可以禁用这个机制?在
或者,为什么8192字节的读取不能从缓存中获益?在
是的,默认缓冲区大小为8k。请参阅^{} :
以及
以及module source code:
^{pr2}$如果使用^{} interface 或包装器对文件进行更改,缓冲区将自动更新(以二进制模式打开文件将生成一个} ,^{} 或{a6}之一)。在
BufferedIOBase
子类,^{对于第二种情况,} for more details
seek()
调用将刷新该缓冲区,因为您查找的是“current”块范围之外的内容(当前位置位于第二个缓冲块的第一个字节8192
,您将返回到0
,这是第一个缓冲块的第一个字节)。参见source code of ^{如果您需要从其他进程编辑底层文件,那么使用} attribute 转到底层^{} implementation 。在
seek()
是一种很好的方法,可以确保在尝试再次读取之前删除缓冲区,或您可以忽略缓冲区,通过^{相关问题 更多 >
编程相关推荐