[ATC'19] Asynchronous I/O Stack: A Low-latency Kernel I/O Stack for Ultra-Low Latency SSDs
Intro
优化I/O的方法
- 用户层面直接调用外部存储设备,需要应用包含文件系统的调用,臃肿,同时不同应用和用户间的冲突问题。
- 优化操作系统内核的I/O 栈
- 使用轮询来减少上下文切换的开销
- 在底层减少一半的中断处理
- 分散I/O指令
- I/O block调度机制
Related Work
减少内核的开销
- 减少中断处理的后半部分
- 是用轮询技术而非中断,减少上下文切换
- 混合轮询
- 基于SSD的闪存随机读写简化调度策略
- 在NVMe固件中进行调度
- 对高优先级的任务,提供不同的IO path支持,最小化IO path的开销
修改存储接口
- 分散/分散 IO合并多个IO到一个指令,减少往返次数
- 移除doorbell机制和完成信号
改善fsync
- 冲fsync请求发出到收到response,延长数据持久化的时间
- 在日志提交记录中使用校验和,有效的重叠日志写入和块写入
- 提出
写守序系统调用
,重叠的fsync效果相同,当应用需要使用fsync时,关于IO的操作将同步进行
用户层直接访问外设,存在隔离、保护等安全问题
Motivation
背景
现状:
- I/O 请求过程中太多的步骤
- 页面缓存分配和索引
- DMA,一系列数据结构的创建
目前的 ULL SDD实现了低于10微妙的IO延迟,然而操作系统内核产生的延迟没有明显变化
本文专注于:
- Linux内核中的
read()
和write()+fsync()
- 基于NVMe SSD的Ext4文件系统
For Read Path
研究发现许多剩余的操作不必在设备I/O之前或之后执行
此类操作可以在设备I/O操作进行时执行
因为此类操作大多独立于设备I/O操作,因此考虑让这些操作与IO重叠
For Write Path
缓冲写write()
,并不发起IO请求,不能异步处理
由于fsync的回写机制和文件系统崩溃一致性(日志系统),包含部分IO请求
由于文件系统带来的三次IO操作
- 数据块写
- jbd2发起写入日志Block I/O
- 提交Block I/O
这些IO的创建,涉及众多过程(block分配,请求缓冲页,创建和提交bio,设置DMA地址),因此可以让CPU将这些前置操作在IO请求发起前预执行。
For Lightweight Block Layer
传统Block Layer涉及过多过程,推迟了IO指令提交给设备的时间
因为ULL SSD的高速随机IO性能和低速的顺序IO,请求重排的效果很低
简化block layer,针对异步IO stack进行优化
Design
轻量化的Block I/O Layer
LBIO,为LL NVMe SSD而设计,只支持IO submission/completion和IO指令tagging
只使用lbio
来表示一个block I/O请求,减少了bio-to-request
的时间
每个lbio包括
- LBA
- I/O 长度
- 复制的页面
- 页面的DMA地址
使用全局的lbio二位数组来记录
行的个数为CPU核心数,行成组被分配到一个NVMe队列
例如8核心,4NVMe队列,每个队列分配2个核心的lbio 当核心数等于队列数时,可以实现无锁的命令提交
lbio在全局数组中的索引用作NVMe指令的tag,减少了之前赋tag的过程
lbio提交后,调用nvme_queue_lbio
来提交I/O指令
LBIO不会合并和调度IO请求
Read Path
Ext4文件系统中,由extent status tree保存缓存到物理文件block的映射
预加载映射到内存中,当树太大时,可以只对某个文件预加载
异步页面申请和DMA分配
提前分配空闲页池
为了减少页面DMA的分配,为每个核维护一个DMA映射空闲页(4KB DMA映射页的链表)
当空闲页池不够用时,将退化为同步进行(origin)
缓存页索引
自旋锁防止并发问题,影响效率
在请求发出,但是页面还没有更新时,可能重复请求更新页面
解决方案是不限制request,在request completion阶段解决问题
尽管多个block请求,但是只能有一个页面被索引
对于其他页面,标记为abandoned,中断发生之后,如果标记为abandoned,则清除已经完成的页面
DMA解除映射
原本使用中断来处理,改为当系统空闲或等待一个IO请求时处理
该方式可能会产生漏洞窗口,若不受到恶意访问,不会产生影响,否则用户可以自行选择关闭惰性DMA映射接触
Write && fsync Path
当fsync涉及文件系统中事务时,可以将jbd2日志处理重叠处理
Experiment
基于Linux内核5.0.5版本
使用文件描述符O_AIOS
Evaluation
Conclusion
提出了AIOS
LBIO层
AIOS将I/O路径中的同步操作替换为异步操作,以将与读取和fsync相关的计算与设备I/O访问重叠。
AIOS在Optane SSD上实现了一位数微秒的I/O延迟。
此外,AIOS通过Z-SSD和Optane SSD上的模拟实验和实际测试显著降低延迟和性能改进。
一些启发
- 优化I/O可以从CPU的空闲时间分析,需要考虑内核和文件系统的工作流程,最大程度的利用CPU资源,减少空闲。
- 硬件设备在发展的同时,软件应该提供必要适配
- 减少内核中与I/O相关的结构类型转化,可以有效节省时间开销
- 惰性修改会存在安全问题,在保证安全的情况下,可以提高效率