Prefetch(预取)是 Linux 内核中的一种性能优化机制,它通过预测应用程序接下来可能需要的数据并提前将其加载到内存中,从而减少I/O等待时间,提高系统性能。
Linux 主要通过以下几种方式实现预取功能:
这是最常见的预取形式,由内核的页面缓存子系统实现:
- 当检测到顺序读取模式时,内核会提前读取后续数据块
- 由 /sys/block/<device>/queue/read_ahead_kb
参数控制预读大小
- 可通过 blockdev --setra
命令调整
CPU 硬件级别的预取:
- 现代 CPU 有硬件预取器,可预测内存访问模式
- 可通过 msr-tools
包中的 rdmsr
和 wrmsr
调整
- 通常不需要手动配置
posix_fadvise()
系统调用允许应用程序提示内核其访问模式madvise()
系统调用可用于提供内存访问建议readahead()
系统调用显式触发文件预读# 查看块设备预读值
cat /sys/block/sda/queue/read_ahead_kb
# 或使用 blockdev 命令
blockdev --getra /dev/sda
# 临时设置预读值 (单位为512字节扇区)
echo 256 > /sys/block/sda/queue/read_ahead_kb
# 或使用 blockdev 命令 (单位为512字节扇区)
blockdev --setra 512 /dev/sda
# 永久设置 (添加到/etc/rc.local或类似启动脚本)
// 使用 posix_fadvise 提示顺序访问
posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
// 使用 readahead 系统调用触发预读
readahead(fd, offset, length);
考虑调整预取设置的场景: 1. 服务器主要运行大型顺序I/O操作(如数据库、视频流) 2. 系统有大量空闲内存可用于缓存 3. 观察到磁盘I/O成为性能瓶颈 4. 工作负载具有可预测的访问模式
Linux的预取机制大多数情况下能自动良好工作,只有在特定工作负载下且经过基准测试验证后才建议调整默认设置。