现代异步存储访问API探索:libaio、io_uring和SPDK

news2024/11/16 11:35:59

【摘要】

最近的高性能存储设备暴露了现有软件栈的低效,因而催生了对I/O栈的改进。Linux内核的最新API是io_uring。作者提供了第一个针对io_uring的深度研究,并且和libaio、SPDK比较,探讨它的下性能和优缺点。根据作者的发现,(1)轮询能极大影响性能(2)只要CPU核足够多,io_uring可以提供和SPKD接近的性能(3)在多核CPU和多设备场景下扩展需要仔细的考虑并且需要一个混合方案。最后,作者为存储密集的应用开发者提供了设计指导。

【三种API简介】

1、libaio

传统的同步I/O接口包括read()、write()、pread()、pwrite()等,线程开始I/O操作后立刻进入阻塞状态,直到I/O请求完成。而使用异步I/O接口,如aio,线程把I/O请求发送给内核后可以继续做其他工作,直到内核把I/O请求完成的信号发送给线程。通常,异步I/O接口效率更高,其中的核心系统调用是io_submit(用于提交I/O请求)和io_getevents(用于获得完成的I/O请求)。然而,在每个I/O操作中,libaio要依赖两个系统调用,而且使用中断的方式通知I/O请求的完成,这导致libaio的单个I/O性能并不好,如下图。

​2、SPDK

SPDK是Linux的高性能API。它在用户空间映射了PCIe寄存器以配置CQ和SQ,用户通过轮询CQ来捕获I/O请求的完成,而不需要中断和系统调用。SPDK的缺点是它很复杂,而且相对于libaio适用范围很窄。SPDK不支持文件系统,也无法利用内核存储服务,如访问控制、调度、QoS和配额管理。

3、io_uring

io_uring中和了上述两类API的优缺点。它在用户空间实现了两个环形数据结构,同时内核可以访问它们,类似于NVMe的CQ和SQ,submission ring存储了用户提交的I/O请求,completion存储了I/O请求的完成结果。用户可以不通过系统调用插入和检索两个环。

io_uring提供的I/O机制有三种,如下图:

​默认模式下,用户可以通过io_uring_enter系统调用通知内核新请求已经提交到SQ中。用户使用同一个io_uring_enter系统调用等待I/O请求完成。io_uring_enter支持中断模式(a)和轮询模式(b)。当然,因为用户也可以访问CQ,所以用户可以自己轮询CQ等待I/O请求完成,而不使用任何系统调用。并且,io_uring也可以使用一个内核线程轮询SQ,这样在整个I/O操作中不会使用任何系统调用(c)。

相关视频推荐

spdk的nvme 开启存储底层的神秘面纱

用spdk实现一个自己的文件系统(200行代码)

8个方面讲解io_uring,重塑对异步io的理解

免费学习地址:c/c++ linux服务器开发/后台架构师

需要C/C++ Linux服务器架构师学习资料加qun812855908获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

【性能测试分析】

实验使用fio生成4KB随机读负载,不使用page cache。纯读负载能达到更高的IOPS,而高IOPS有助于分析不同API的可扩展性趋势和每个I/O操作的开销。除了io_uring外,其他API均使用默认配置。io_uring的配置如下:

(1)iou:上图(a)的配置(默认的fio参数)

(2)iou+p:上图(b)的配置(fio参数是hipri)

(3)iou+k:不使用系统调用,即使用内核线程轮询I/O的提交,同时应用轮询I/O的完成(fio的参数是sqthread_poll)

环境配置如下表:

​P.S. 虽然io_uring里提供了io_uring_enter作为提交I/O请求和捕获完成的I/O请求的统一接口,但FIO里面还是分开使用了(即调用了两次io_uring_enter)。

1、理解轮询

作者使用单个fio job、单个NVMe驱动和单个CPU,在不同队列深度下,测试三种API(libaio、io_uring和SPDK)的KIOPS,如下图:

​每个IOPS下对应的延迟中位数如下图:

​平均每个I/O操作进行的系统调用个数如下图:

​① 可知,iou+k的KIOPS仅仅13,比其他API少一个数量级。因为此时fio线程和内核轮询线程共享一个CPU,减少了FIO每秒处理的I/O请求的数量。同时,iou+k的延迟是8ms,比其他API慢1~2个数量级。iou+k的延迟不随KIOPS的变化而变化,因为此时的延迟取决于CPU资源的竞争,而非排队等待。

当CPU数量增加到2时,iou+k的性能完全恢复了,如下图:

​每个KIOPS对应的延迟中位数为:

​此时,iou+k的性能仅次于SPDK:最大带宽比SPDK小18%,延迟和SPDK相当。

② SPDK在所有场景下性能最好,也是唯一达到驱动带宽上限的API。SPDK和iou+k的区别在于,iou+k使用两个线程访问同一个变量,会产生原子访问和缓存失效的开销,而SPDK使用一个线程,能更加充分的利用资源。

③ 当IOPS较小时,iou+p的性能和SPDK接近,因为队列深度较小时,系统调用的开销还不足以成为性能瓶颈,此时系统态轮询和用户态轮询的性能接近。类似的还有iou和libaio,当队列深度小于16时,二者KIOPS和延迟都很接近,当队列深度大于16后,iou的KIOPS和延迟比libaio要好——因为iou使用的系统调用比libaio少,所以可以更加充分的利用CPU资源。

当队列深度小于16时,iou的系统调用比iou+p少,但延迟比iou+p高。原因是,队列较浅时,fio的队列很快会被填满,而当队列满时,fio会等待至少一个请求完成再进行下一步动作。此时,虽然中断比较慢,但iou可能会一次处理较多完成的请求,而轮询则是检测到一个请求完成就退出,从而错失了批量处理多个完成的请求的机会。当队列深度增加时,两个API最后都趋向于每个I/O请求只使用1个系统调用。

iou和libaio的最大区别是,iou多了一个提交队列(SQ),这就是它具有批处理能力的原因。

2、不同的CPU-设备比

作者进一步分析了对于iou+k,每个驱动需要多少个CPU以获得最佳性能。此时,作者使用了J=5个FIO job测试,每个job运行在不同的驱动上,队列深度为128,C代表CPU的数目,本次实验中,分别测试了C=J,C=J+1,C=J+2和C=J*2的情况。

注意,在iou+k中,内核会为每个job产生一个内核线程以轮询SQ获得提交的请求。

实验结果如下图:

​可见,除了iou+k,其他API的带宽表现和CPU-设备比无关。而iou+k需要两倍于驱动数的CPU才能达到最好的性能——即每个线程需要一个单独的CPU来轮询。糟糕的是,当CPU数不是最佳时,iou+k的KIOPS是最低的。这一实验结果揭示了iou+k要实现高性能的隐藏开销,而其他测试忽略了这一点。

3、可扩展性

作者控制job从1到20,以测试不同API的可扩展性。每个job访问不同的驱动,设置CPU数C=2*J(由于硬件限制,C最大可以取到20),队列深度为128。下图是测试结果:

​SPDK的性能总是最好的,而性能第二好的API取决于job的数量和CPU核的数量。当J不大于10时,iou+k可以给每个内核线程分配一个CPU,性能最好。此后随着J的增大,内核线程和应用线程开始抢夺CPU资源,KIOPS开始下滑。在J=12时,iou+k和iou、iou+p的KIOPS交汇,在J=14时,iou+k成为性能最差的API。其他的API随着job的增长,KIOPS也基本上稳定增长。

iou和iou+p的性能很接近,libaio的带宽也仅仅比iou、iou+p少10%。

【总结与讨论】

1、不同的轮询方式各有特点

  • lSPDK的优势不仅仅体现在用户态轮询、无系统调用开销,还体现在使用单个线程进行轮询。

  • liou+k的优势在CPU不够时不明显。

  • liou+p使用系统级轮询,在队列深度较小时可以和SPDK相当。

2、io_uring在特定配置下的性能接近SPDK3、性能的可扩展性需要仔细考虑

虽然SPDK的性能最好,但需要放弃Linux文件的支持。如果需要使用文件系统,且CPU足够多,iou+k是不错的选择(可以达到90% SPDK的性能),而若CPU资源不足,可以使用iou+p,当队列深度不深时和SPDK的性能接近。

未来可以在更在实际的I/O密集型应用上测试,如数据库。它们都需要文件系统的支持,可能会带来额外的同步开销,可能会覆盖I/O路径上的bottleneck。此外还可以研究更高效的iou+k设计,如不同的应用线程共享一个内核轮询线程,或者二者更好的使用CPU资源等。最后,io_uring支持socket I/O,所以它的性能也可以测试以评估网络应用的表现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/713029.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT:对教育来说,究竟是机遇,还是风险?

ChatGPT(Chat Generative Pre-trained Transformer)是由美国人工智能研究实验室OpenAI推出的一款人工智能聊天机器人。作为一个大型语言模型,ChatGPT有效结合了大数据、大算力、强算法,拥有较强的语言理解和文本生成能力&#xff…

javaMail之巨坑

使用java实现邮件发送功能&#xff0c;环境&#xff1a;Foxmail 6.5&#xff0c;阿里EasyExcel生成的excel文件&#xff0c;maven依赖如下&#xff1a; <dependency><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId><ver…

MySQL - 第12节 - MySQL视图特性

目录 1.MySQL视图特性 2.基本使用 2.1.准备测试表 2.2.创建视图 2.3.修改视图影响基表 2.4.修改基表影响视图 2.5.删除视图 3.视图规则和限制 1.MySQL视图特性 视图的概念&#xff1a; • 视图是一个虚拟表&#xff0c;其内容由查询定义&#xff0c;同真实的表一样&…

一些零散的查询知识

一、all any some 表&#xff1a; all大于所有的值&#xff1a; any some:大于任意一个即可 例题&#xff1a; 大于50部门所有员工工资的人&#xff1a; 等价于&#xff1a; 二、exists关键字 1、exists查询 exists(子查询) 如果有满足条件的记录&#xff0c;那么exi…

nginx配置https加密

以下操作版本为Ubuntu2004&#xff0c;文件位置可能略有不同 https 功能 Web网站的登录页面通常都会使用https加密传输的&#xff0c;加密数据以保障数据的安全&#xff0c;HTTPS能够加密信息&#xff0c;以免敏感信息被第三方获取&#xff0c;所以很多银行网站或电子邮箱等等…

计算机网络 第二章(上)

2.1_1 物理层基本概念_哔哩哔哩_bilibili2.1_1 物理层基本概念是王道计算机考研 计算机网络的第12集视频&#xff0c;该合集共计76集&#xff0c;视频收藏或关注UP主&#xff0c;及时了解更多相关视频内容。https://www.bilibili.com/video/BV19E411D78Q/?p12&spm_id_from…

【近场社交项目】数据库系统期末设计——需求分析部分

【近场社交项目】数据库系统设计——需求分析&#x1f60e; 前言&#x1f64c;1.需求求分析(用户部分为例&#xff09;1.2用户数据字典1.2.1用户信息表&#xff08;数据结构&#xff09;&#xff1a;数据项间的关系和结构定义&#xff1a; 1.2.2.个人资料表&#xff08;数据结构…

10、SpringBoot集成Redis

总体概述 jedis-lettuce-RedisTemplate三者的联系 本地Java连接Redis常见问题 ● bind配置请注释掉 ● 保护模式设置为no ● Linux系统的防火墙设置 ● Redis服务器的IP地址和密码是否正确 ● 忘记写Redis的服务端口号和auth密码 1、集成Jedis 是什么 Jedis Client是Redis官…

【MATLAB笔记】基础函数及向量

一、基础函数绘制 版本&#xff1a;Matlab2021a 实例1&#xff1a;生成向量 >> x0:0.1:30; >> ysin(x).*cos(x); >> plot(x,y) 实例2&#xff1a;创建向量 >> xlinspace(0,2*pi); >> ysin(x) >> plot(x,y) 二、向量的点积 >> a…

ueditor富文本编辑器使用

下载百度富文本编辑器 链接&#xff1a;https://pan.baidu.com/s/1E4K8e0WCy9_L6z0-Dz3JkQ?pwdc2gf 提取码&#xff1a;c2gf <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" co…

pgrouting连通性分析

官方文档 1、安装pgrouting库 参考&#xff1a;pgrouting安装 主要涉及的两个函数&#xff1a; 1、 pgr_createTopology&#xff1a;创建空间拓扑&#xff0c;数据自动保存至新创建的表<edge_table>_vertices_pgr&#xff0c;将空间表的linestr的geometry数据拆分&…

云原生系列之管理docker容器中的数据管理实战

前言 在生产环境中使用docker,一方面需要对数据进行保存或者在多个容器之间进行数据共享; 另一方面在docker的容器被删除之后,并不会保留容器的状态信息。 想要实现docker容器的信息持久化,就涉及到docker的数据管理,今天我们就来聊聊docker数据管理那些事。 文章目录 …

Vue3:在 VSCode 中如何成功安装 Mockjs 及成功引入 Mock 的详细过程

Ⅰ、Mock 简介&#xff1a; 1、什么是 Mock&#xff1f; 其一、Mock 的解释一&#xff1a; Mock 服务是指在测试过程中对于某些复杂&#xff08;或者不太好构造&#xff09;的对象&#xff0c;用一个虚拟的对象替代它&#xff1b;对于前端来说&#xff0c;就是后台数据还没有…

Python编程入门:了解Python及其由来

在计算机编程的世界中&#xff0c;Python已经成为一门备受欢迎的高级编程语言。它的简洁、易读和功能强大使得它成为众多开发者的首选。但你是否了解Python的由来以及为什么它如此受欢迎呢&#xff1f;在本篇博客中&#xff0c;我们将一起探索Python编程语言的起源和一些相关知…

shell中awk命令常用用法总结

1、获取分隔的内容 以点为分隔符获取IP地址的最后一个字段 echo $ip | awk -F . {print $4}

YOLO系列v1-v8

YOLO是Region-free方法&#xff0c;只需要一次扫描&#xff0c;也被称为单阶段&#xff08;1-stage&#xff09;模型。而Region-based方法方法&#xff0c;如mask-rcnn &#xff0c;被称为两阶段&#xff08;2-stage&#xff09;方法。 YOLOv1-v3是原作者&#xff0c;v4和v7是…

【C语言】指针进阶[下](回调函数(模拟实现qsort-采用冒泡方式))

简单不先于复杂&#xff0c;而是在复杂之后。 目录 1. 回调函数 1.1 qsort 函数的使用 1.2 qsort 排序结构体类型 1.3 回调函数模拟实现 qsort&#xff08;排序整型&#xff09; 1.4 回调函数模拟实现 qsort&#xff08;排序结构体类型&#xff09; 1. 回调函数 回…

【WebAssembly】编译c++ Demo ->HelloWorld

好的开始等于成功了一半&#xff0c;本篇逐条讲解如何将一个cpp通过WebAssembly编译并运行在网页上。 一、环境准备 前提条件 需要安装CMake&#xff0c;VS&#xff0c;python2.7及以上 拉取emsdk代码 仓库地址&#xff1a;GitHub - emscripten-core/emsdk: Emscripten SD…

04_前端包管理工具模块化

注意事项: ​ 改模块代码不用重启服务器,修改config文件的时候需要重启服务器 ​ nvm的安装路径和node的安装路径不能在同一路径下面 ​ 有乱码问题使用管理员权限进行使用use方法 下载安装node ​ 使用命令进行安装 1.nvm list 查看已下载所有的node版本 2.nvm install…

VR工地安全虚拟现实体验:多种事故模拟,第三人称回看

建筑工地五大伤害是指&#xff1a;高处坠落、坍塌、物体打击、机械伤害、触电。利用VR(虚拟现实)技术体验建筑工地五大伤害&#xff0c;可以为建筑工人提供更真实、更安全的工作环境&#xff0c;同时也可以帮助他们更好地了解和掌握工作技能。 以下是VR工地安全虚拟现实体验软件…