跳到主要内容
返回时间线
arXiv来源发表:

存储预取不再只认文件偏移:把预测交给用户态,应用冷启动少等5.3%到26.3%

核心概要

Linux 的通用预取只按最近的文件偏移猜下一页,遇到启动时稀疏跳读、B 树按键序遍历、大模型按张量布局加载就失效。PredictIO 把预测和执行拆开:内核把观测到的访问和应用提示送到用户态策略,策略只输出统一的页范围请求,再由内核后端校验、限流并异步发起预取。在应用启动、SQLite 范围扫描和 llama.cpp 模型加载上,延迟分别降低 5.3–26.3%、扫描最高加速 2.99 倍、加载降低 8.8–47.9%。

Source-provided article image: PredictIO: Decoupling Workload Prediction from OS-Controlled Storage Prefetching
Figure 2 · arXiv

深度剖析

预取被拆成两件事:用户态策略决定该取哪些页,内核只负责校验和发起异步读。 此前 Linux 的通用 readahead 把预测和执行都放在内核里,只能依据最近的文件偏移和页缓存状态推断下一页。 在应用启动、SQLite 范围扫描和 llama.cpp 模型加载三类负载上,同一套事件路径和请求接口把冷启动延迟降低 5.3–26.3%,SQLite 扫描最高加速 2.99 倍,模型加载延迟降低 8.8–47.9%。

策略通过两条路径接入:事件路径把内核观测或应用提示送进用户态,请求路径把预测结果送回内核执行。 此前面向具体负载的预取逻辑往往嵌在单个应用里,并与该应用的 I/O 路径绑定,难以跨负载和系统复用。 原型用 eBPF 观测未修改应用的页级文件访问,用 Unix 域数据报套接字接收 SQLite、LMDB、RocksDB 和 llama.cpp 的提示,再经共享内存环把页范围交给内核工作线程异步执行。

内核后端对预测做有界执行:先跳过已缓存、在途、越界或落在稀疏空洞里的页,再按队列容量和在途页上限提交异步读。 此前应用自带的预取机制各自重复实现页缓存协调,容易产生冗余 I/O,也难以限制错误预测带来的带宽浪费。 同一套树感知策略不改预测逻辑、只换轻量适配器,就在 SQLite 上降低 34.3% 延迟、在 LMDB 上降低 32.0%;RocksDB 原生 readahead 迁移后,长顺序扫描相对基线约 4.6 倍加速,而 YCSB-C 点读场景下与基线接近,说明选择性得以保留。

启示与展望

这套机制面向块设备文件系统,内核后端依赖 bmap() 支持,当前原型在 Linux 6.6.138 与 Ext4 上实现。演示范围是应用冷启动、SQLite 范围扫描和 llama.cpp 模型加载三类负载,并覆盖 NVMe SSD、SATA SSD 和 SATA HDD。策略迁移的效果随负载而变:长顺序扫描受益最大,短扫描和点读场景收益有限。

收益大小取决于负载中可预测访问所占的比例:Firefox 和 VSCode 提升明显,Shotcut 因元数据和单文件开销占比高而收益较小,PyCharm 的启动时间更多花在计算和运行时初始化上。在 HDD 上,推测读与需求读直接竞争,收益随设备变慢而下降;LLM 加载在 HDD 上收益很小,因为加载受顺序带宽而非缺页延迟主导。