Python有8KiB字节长的文件I/O缓存吗?

2024-05-14 13:59:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在研究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字节的读取不能从缓存中获益?在


Tags: 文件in脚本forreadstringrangeseek
1条回答
网友
1楼 · 发布于 2024-05-14 13:59:52

是的,默认缓冲区大小为8k。请参阅^{}

io.DEFAULT_BUFFER_SIZE
An int containing the default buffer size used by the module’s buffered I/O classes. open() uses the file’s blksize (as obtained by os.stat()) if possible.

以及

>>> import io
>>> io.DEFAULT_BUFFER_SIZE
8192

以及module source code

^{pr2}$

如果使用^{} interface或包装器对文件进行更改,缓冲区将自动更新(以二进制模式打开文件将生成一个BufferedIOBase子类,^{}^{}或{a6}之一)。在

对于第二种情况,seek()调用将刷新该缓冲区,因为您查找的是“current”块范围之外的内容(当前位置位于第二个缓冲块的第一个字节8192,您将返回到0,这是第一个缓冲块的第一个字节)。参见source code of ^{} for more details

如果您需要从其他进程编辑底层文件,那么使用seek()是一种很好的方法,可以确保在尝试再次读取之前删除缓冲区,您可以忽略缓冲区,通过^{} attribute转到底层^{} implementation。在

相关问题 更多 >

    热门问题