mmap读大文件不一定更快,因其仅建虚拟映射,首次访问才触发缺页加载;随机跳转易致频繁缺页反而更慢,需针对只读、重复搜索或固定结构体场景优化使用。

为什么直接用 mmap 读大文件不一定更快
直接把整个大文件 mmap 进内存,并不等于“自动加速”。操作系统只是建立了虚拟地址映射,真正触发磁盘 I/O 的是第一次访问对应页——如果搜索逻辑导致随机跳转、频繁缺页,反而比顺序 read() 更慢。关键不是“用了 mmap”,而是“怎么用它避开拷贝和重复扫描”。
实操建议:
- 只对需要反复搜索的只读大文件(如日志、二进制数据块)考虑
mmap;写入场景慎用,mmap同步行为复杂且易出错 - 避免用
mmap+str.find()搜索 UTF-8 文本:编码边界可能跨页,find()会隐式解码失败或漏匹配;优先用字节模式(bytes)操作 - 若文件远大于物理内存,
mmap可能引发大量 swap,观察vmstat的si/so值比盲目上mmap更有用
mmap 搜索固定长度记录最稳
当文件由等长结构体(如 512 字节日志条目、4KB 数据块)组成时,mmap 能发挥最大价值:直接按偏移计算地址,零拷贝跳转,配合 struct.unpack_from() 解析,比逐行 readline() 快 3–10 倍。
示例:查找第 1000 个 64 字节记录中字段 status == 0x01
import mmap
import struct
<p>with open("data.bin", "rb") as f:
mm = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
offset = 1000 * 64</p><h1>直接从 mmap 区域解包,不复制到 Python bytes</h1><pre class="brush:php;toolbar:false;">status = struct.unpack_from("B", mm, offset + 4)[0] # 假设 status 在偏移 4
if status == 0x01:
print("found")
mm.close()
注意点:
- 必须用
access=mmap.ACCESS_READ(默认是ACCESS_WRITE,会触发写时复制,浪费内存) -
struct.unpack_from第二个参数可直接传mm,它实现了 buffer protocol - 不要在循环里反复调用
mm.seek() + mm.read()—— 这会退化成普通 I/O
用 mmap 替代 readlines() 做文本行搜索要绕开换行符陷阱
文本文件无法像二进制那样靠固定偏移跳转,但可以用 mmap 配合 find(b"\n") 实现高效行定位,避免把整文件读进内存再 splitlines()。
常见错误现象:mm.find(b"\n", start) 返回 -1 却没检查 EOF,或误用 str.splitlines() 处理 mm[start:end] 导致 UnicodeDecodeError
实操建议:
- 始终用
bytes操作:搜索b"\n"、b"\r\n",切片结果也保持为bytes,解码只在必要字段做 - 用双指针扫描代替
for line in mm.readline()(mmap对象没有readline方法) - 若需正则匹配整行,用
re.search(pattern, mm[i:j]),别用re.findall全局扫——它会强制遍历全部内容
Windows 下 mmap 映射超 4GB 文件要加 offset 参数
Windows 的 CreateFileMapping API 对 offset 使用 32 位整数,若不显式指定 offset,Python 的 mmap 在 64 位系统上仍可能截断高位,导致 OSError: [Errno 22] Invalid argument。
正确写法:
import mmap <h1>错误:可能失败</h1><p>mm = mmap.mmap(f.fileno(), 0)</p><h1>正确:显式设 offset=0,明确告诉系统从头映射</h1><p>mm = mmap.mmap(f.fileno(), 0, offset=0) </p>
更关键的是:如果只映射文件一部分(比如最后 1GB),必须确保 offset 和 length 都是 64 位安全值,且 offset 是页面对齐的(通常 4096 字节),否则 mmap 直接抛异常。
容易被忽略的地方:Linux 下这个问题不明显,所以跨平台代码里常漏掉 offset=0,一到 Windows 就崩——不是功能问题,是 API 底层限制。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











