【发布时间】:2018-01-03 08:40:24
【问题描述】:
我正在研究 Python 3.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 看到以下操作正在发生(井号行是我的 cmets):
# Initial write
Offset: 0, Length: 1.000.000
# The 3 8191-long reads only produce one syscall due to caching:
Offset: 0, Length: 8.192
# However, if the read length is exactly 8192, python doesn't take advantage:
Offset: 0, Length: 8.192
Offset: 0, Length: 8.192
Offset: 0, Length: 8.192
# Due to caching, the first syscall of the first read of the last loop is missing.
Offset: 8.192, Length: 8.192
Offset: 0, Length: 8.192
Offset: 8.192, Length: 8.192
Offset: 0, Length: 8.192
Offset: 8.192, Length: 8.192
# Afterwards, 2 syscalls per read are produced on the 8193-long reads.
首先,很明显 python 会读取 8KiB 的倍数的文件。
我怀疑 python 实现了一个缓存缓冲区,用于存储最后读取的 8KiB 块,如果您尝试连续多次读取相同的 8KiB 范围,它将简单地返回并裁剪它。
有人可以确认python确实实现了这种机制吗?
如果是这种情况,这意味着如果您不以某种方式手动使缓存无效,python 将无法检测到外部应用程序对该块所做的更改。那是对的吗?也许有办法禁用这个机制?
(可选)为什么恰好 8192 字节的读取不能从缓存中受益?
【问题讨论】:
-
您真正想做什么?如果您想确认实际行为,请阅读源代码™。
-
当你打开一个文件时,有一个可选的buffer参数,这里默认使用操作系统默认的缓冲模式,但是你可以指定它应该是无缓冲的。
标签: python windows python-3.x caching file-io