io_uring vs epoll ,谁在网络编程领域更胜一筹?

简介:从定量分析的角度,通过量化 io_uring 和 epoll 两种编程框架下的相关操作的耗时,来分析二者的性能差异。

3.jpg

本文作者:王小光,「高性能存储技术SIG」核心成员。

背景

io_uring 在传统存储 io 场景已经证明其价值,但 io_uring 不仅支持传统存储 io,也支持网络 io。io_uring 社区有众多的开发者尝试将 io_uring 用于网络应用。我们之前也在《你认为 io_uring 只适用于存储 IO?大错特错!》中也探索过 io_uring 在网络场景的应用及其与传统网络编程基石 epoll 的对比,当时我们的测试结果显示在 cpu 漏洞缓解使能的前提下,io_uring 相比于 epoll 可以带来一定的优势,在 cpu 漏铜缓解未使能时,io_uring 相比于 epoll 没有优势,可能还会存在性能下降。

在 io_uring 社区,关于 io_uring 和 epoll 孰优孰劣也一直存在争论,有些开发者宣称 io_uring 可以获得比 epoll 更好的性能,有些开发者则宣称二者性能持平或者 io_uring 甚至不如 epoll。相关的讨论非常多,具体可参见如下两例:

https://github.com/axboe/liburing/issues/189

Wild results, cannot reproduce · Issue #8 · frevib/io_uring-echo-server · GitHub

以上讨论从 2020 年 8 月一直持续到现在,其过程非常长也非常地激烈。可以看出 io_uring 和 epoll 在网络编程领域孰优孰劣目前确实比较难以达成共识。

目前很多业务想将 io_uring 在网络场景应用起来,但 io_uring 是否能比 epoll 带来性能提升,大家或多或少存在些许疑问。为了彻底厘清这个问题,龙蜥社区高性能存储 SIG尝试从定量分析的角度,通过量化 io_uring 和 epoll 两种编程框架下的相关操作的耗时,来分析二者的性能差异。

评估模型

我们仍然选用 echo server 模型进行性能评估,server 端采用单线程模型,同时为公平对比,io_uring 不使用内部的 io-wq 机制(io_uring 在内核态维护的线程池,可以用来执行用户提交的 io 请求)。epoll 采用 send(2) 和 recv(2) 进行数据的读写操作;而 io_uring 采用 IORING_OP_SEND 和 IORING_OP_RECV 进行数据的读写操作。

结合 echo server 的模型,我们分析有四个因素会影响 io_uring 和 epoll 的性能,分别是:

1、系统调用用户态到内核态上下文切换开销,记为 s

2、系统调用自身内核态工作逻辑开销,记为 w

3、io_uring 框架本身开销,记为 o

4、io_uring 的 batch 量,记为 n,epoll 版 echo server 由于直接调用 recv(2) 和 send(2), 其 batch 实际为 1。

同时在本文中我们仅评估 io_uring 和 epoll 请求读写操作的开销,对于 io_uring 和 epoll 本身的事件通知机制本身不做衡量,因为通过 perf 工具分析,读写请求本身开销占据绝大部分。系统调用用户态到内核态上下文切换开销可以通过专门的程序进行测量,因素 2、3、4 等可以通过衡量内核相关函数的执行时间进行测量,用 bpftrace 进行分析。

epoll 版 echo server 开销度量

从用户态视角,send(2) 或者 recv(2) 开销主要包含两个方面,系统调用用户态到内核态上下文切换开销和系统调用自身内核态工作逻辑开销,其中系统调用本身工作逻辑的开销,send(2) 和 recv(2) 分别衡量 sys_sendto(), sys_recvfrom() 即可。

由于 epoll 场景下其系统调用的 batch 为 1,因此 epoll  模型下收发请求的平均耗时为 (s + w)

io_uring 版 echo server 开销度量

io_uring 中 io_uring_enter(2) 系统调用既可以用来提交 sqe,也可以用来 reap cqe,两种操作混合在一个系统调用中,准确衡量 sqe 的提交收发请求的耗时比较困难。简单起见,我们采用跟踪 io_submit_sqes() 的开销来衡量 IORING_OP_SEND 和 IORING_OP_RECV 的开销,此函数被 io_uring_enter(2) 所调用。io_submit_sqes() 包含send(2) 和 revc(2) 内核侧工作逻辑开销,及 io_uring 框架的开销,记为 t

同时我们采用 io_uring 的 multi-shot 模式,从而确保 io_submit_sqes() 中的提交的 IORING_OP_SEND 和 IORING_OP_RECV 请求都可以直接完成,而不会用到io_uring的 task-work 机制。

由于 io_uring 场景下可以 batch 系统调用的执行,因此 io_uirng 模型下收发请求的平均耗时为 (s + t) / n

实际度量

我们测试环境 Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz,衡量 echo server 单链接性能数据。

用户态内核态系统调用上下文切换开销

cpu 漏洞对系统调用用户态内核态上下文切换的影响比较大,在我们的测试环境中:漏铜缓解使能时,系统调用的上下文切换开销为 700ns 左右;漏铜缓解未使能时,系统调用的上下文切换开销为 230ns 左右。

epoll 模型下 send(2)/recv(2) 内核侧开销

采用bpftrace 脚本分别衡量 sys_sendto()sys_recvfrom() 即可。 bpftrace 脚本如下:

BEGIN
{@start = 0;@send_time = 0;@send_count = 0;
}
kprobe:__sys_sendto
/comm == "epoll_echo_serv"/
{@start = nsecs;
}
kprobe:__sys_recvfrom
/comm == "epoll_echo_serv"/
{@start = nsecs;
}
kretprobe:__sys_sendto
/comm == "epoll_echo_serv"/
{
if (@start > 0) {@delay = nsecs - @start;@send_time = @delay + @send_time;@send_count = @send_count + 1;}
}
kretprobe:__sys_recvfrom
/comm == "epoll_echo_serv"/
{
if (@start > 0) {@delay = nsecs - @start;@send_time = @delay + @send_time;@send_count = @send_count + 1;}
}
interval:s:5
{
printf("time: %llu\n", @send_time / @send_count);@send_time = 0;@send_count = 0;
}

在单连接,包大小 16 字节场景下,epoll 版的 echo_server 的 tps 在 1000 左右,其 recv(2) 和 send(2) 的内核侧逻辑平均开销如下:

time: 1489、time: 1492、time: 1484、time: 1491、time: 1499、time: 1505、time: 1512、time: 1528、time: 1493、time: 1509、time: 1495、time: 1499、time: 1544

从上述数据可以看出,send(2) 和 recv(2) 的内核侧平均开销在1500ns左右,因此:

1) cpu 漏洞缓解,send(2) 和 recv(2) 的平均开销为 s=700ns,w=1500ns,总共 (s+w) = 2200ns

2) cpu 漏洞为缓解,send(2) 和 recv(2) 的平均开销为 s=230ns,w=1500ns,总共 (s+w) = 1730ns

io_uring 模型下 io_uring_enter(2) 内核侧开销

采用bpftrace 脚本分别衡量 io_submit_sqes() 开销即可。

BEGIN
{@start = 0;@send_time = 0;@send_count = 0;
}
kprobe:io_submit_sqes
/comm == "io_uring_echo_s"/
{@start = nsecs;@send_count = @send_count + arg1;
}
kretprobe:io_submit_sqes
/comm == "io_uring_echo_s"/
{
if (@start > 0) {@delay = nsecs - @start;@send_time = @delay + @send_time;}
}
interval:s:5
{
printf("time: %llu\n", @send_time / @send_count);@send_time = 0;@send_count = 0;
}

运行类似上述 epoll 同样的测试,数据为:

time: 1892、time: 1901、time: 1901、time: 1882、time: 1890、time: 1936、time: 1960、time: 1907、time: 1896、time: 1897、time: 1911、time: 1897、time: 1891、time: 1893、time: 1918、time: 1895、time: 1885

从上述数据可以看出,io_submit_sqes() 的内核侧平均开销在 1900ns 左右,注意此时的batch n=1,且该开销包括收发请求的内核态工作逻辑开销及 io_uring 框架开销。

1) cpu 漏洞缓解,用户态观察到的 io_uring_enter(2) 平均开销为 t=1900ns,n=1,s=700ns,总共 (t+s) / n = 2600ns

2) cpu 漏洞未缓解,用户态观察到的 io_uring_enter(2) 的平均开销为 t=1900ns,n=1,s=230ns,总共 (t+s) / n = 2130ns

注意由于我们实际只 trace io_submit_sqes,而 io_uring_enter(2) 系统调用是调用 io_submit_sqes 的,因此 io_uring_enter(2) 的实际开销是肯定大于 (t+s) / n

数据量化分析

从上述数据发现,cpu 漏洞确实对系统调用的性能影响较大,尤其对于小数据包的场景,我们分别讨论下:

cpu 漏洞缓解未使能

epoll: s+w,  io_uring: (t+s) / n

image.png

可以看出在此种情况下,由于 t 大于 w, 即使扩大 batch,io_uring 的性能也不如 epoll。

cpu 漏洞缓解使能

epoll: s+w,  io_uring: (t+s) / n

image.png

可以看出在此种情况下,由于 s 比较大,当 batch 比较低时,io_uring 不如 epoll,但当 batch 比较大时,io_uring 场景下系统调用上下文切换开销被极大摊薄,此时 io_uring 的性能是优于 epoll。在我们的实际测试中,1000连接时,io_uring 的的吞吐要比 epoll 高 10% 左右,基本符合我们的建模。

结论

从我们的量化分析可以看出 io_uring 与 epoll 孰优孰劣完全由评估模型中定义的 4 个变量决定:

epoll: s + w

io_uring: (t + s) / n

如果某个变量占主导地位,则性能数据会截然不同。举个例子,假设系统调用上下文切换开销 s 很大,而且 io_uring batch n 也很大,则 io_uring 在此种场景下的性能肯定是会比 epoll 好;再比如系统内核侧开销 w 很大,此时 io_uring 和 epoll 性能会接近。

因此 io_uring 和 epoll 孰优孰劣,取决于其应用场景,我们建议的最佳实践是基于业务真实网络模型,将其简化为 echo server 模型,运行我们的度量脚本,从而可以评估二者在真实环境的性能,以指导真实应用开发。同时上述度量数据也为我们的性能优化提供方向,我们可以尽可能的减少某一变量的开销,从而提高性能,比如可以进一步优化 io_uring 框架的开销。

高性能存储技术SIG介绍

高性能存储技术SIG :致力于存储栈性能挖掘化,打造标准的高性能存储技术软件栈,推动软硬件协同发展。

原文链接
本文为阿里云原创内容,未经允许不得转载。 

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

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

相关文章

Redis 为何使用近似 LRU 算法淘汰数据,而不是真实 LRU?

作者 | 码哥呀来源 | CSDN博客在《Redis 数据缓存满了怎么办?》我们知道 Redis 缓存满了之后能通过淘汰策略删除数据腾出空间给新数据。淘汰策略如下所示:redis内存淘汰设置过期时间的 keyvolatile-ttl、volatile-random、volatile-lru、volatile-lfu 这…

量化感知训练实践:实现精度无损的模型压缩和推理加速

简介:本文以近期流行的YOLOX[8]目标检测模型为例,介绍量化感知训练的原理流程,讨论如何实现精度无损的实践经验,并展示了量化后的模型能够做到精度不低于原始浮点模型,模型压缩4X、推理加速最高2.3X的优化效果。 1. 概…

此表单只能填写一次_暴雪战网国服账号修改邮箱只能填写表单申请

暴雪战网国服账号只认身份信息,注册必须实名,而且实名信息千万不要乱填,不然账号出现问题,需要上传证件图片的,客服会核实与注册实名内容是否一致,不然无法帮助玩家解决一些问题。国服账号邮箱没有什么权限…

贾扬清演讲实录:一个AI开发者的奇幻漂流

简介:2021阿里灵杰AI工程化峰会,贾扬清深度解读阿里灵杰大数据和AI一体化平台。 演讲人:贾扬清 演讲主题:一个AI开发者的奇幻漂流 活动:2021阿里灵杰AI工程化峰会 对于绝大多数人来说,这一波AI浪潮兴许…

上云避坑指南100篇|「云」上玩法虽多,小心水土不服

商业智能BI发展至今,从市场增速来看,我国已进入 BI 及 DA(数据分析)领域的第一方阵,并成为发展最快的国家之一。 IDC 数据显示,2020 年中国商业智能软件市场规模为 5.8 亿美元,同比增长 17.1%&a…

如何基于LSM-tree架构实现一写多读

简介:传统MySQL基于binlog复制的主备架构有它的局限性,包括存储空间有限,备份恢复慢,主备复制延迟等问题,为了解决用户对于云上RDS(X-Engine)大容量存储,以及弹性伸缩的诉求,PolarDB推出了历史库…

Dubbo-go v3.0 正式发布 ——打造国内一流开源 Go 服务框架

简介:Dubbo-go 是常新的,每年都在不断进化。介绍 Dubbo-go 3.0 工作之前,先回顾其过往 6 年的发展历程,以明晰未来的方向。 作者 | 李志信 来源 | 阿里技术公众号 作者介绍: 李志信(github laurencelizhix…

谁还没经历过死锁呢?

作者 | 敖丙来源 | 敖丙之前刚学习多线程时,由于各种锁的操作不当,经常不经意间程序写了代码就发生了死锁,不是在灰度测试的时候被测出来,就是在代码review的时候被提前发现。这种死锁的经历不知道大家有没有,不过怎么…

阿里巴巴超大规模Kubernetes基础设施运维体系解读

简介:ASI:Alibaba Serverless infrastructure,阿里巴巴针对云原生应用设计的统一基础设施。ASI 基于阿里云公共云容器服务 ACK之上,支撑集团应用云原生化和云产品的Serverless化的基础设施平台。 作者 | 仔仁、墨封、光南 来源 | …

搜索NLP行业模型和轻量化客户定制

简介:开放搜索NLP行业模型和轻量化客户定制方案,解决减少客户标注成本、完全无标注或少量简单标注的等问题,让搜索领域扩展更易用。 特邀嘉宾: 徐光伟(昆卡)--阿里巴巴算法专家 搜索NLP算法 搜索链路 …

CICD 的供应链安全工具 Tekton Chains

作者 | Addo Zhang来源 | 云原生指北软件供应链是指进入软件中的所有内容及其来源,简单地可以理解成软件的依赖项。依赖项是软件运行时所需的重要内容,可以是代码、二进制文件或其他组件,也可以是这些组件的来源,比如存储库或者包…

python计算不规则图形面积_python opencv中的不规则形状检测和测量

正如我在评论中提到的那样,对于这个问题,分水岭似乎是一个很好的方法.但是当你回答时,定义标记的前景和背景是困难的部分!我的想法是使用形态梯度沿着冰晶获得良好的边缘并从那里开始工作;形态梯度似乎很有效.import numpy as npimport cv2img cv2.imread(image.pn…

深度解析开源推荐算法框架EasyRec的核心概念和优势

简介:如何通过机器学习PAI实现快速构建推荐模型 作者:程孟力 - 机器学习PAI团队 随着移动app的普及,个性化推荐和广告成为很多app不可或缺的一部分。他们在改善用户体验和提升app的收益方面带来了巨大的提升。深度学习在搜广推领域的应用也…

助力公益数字化 火山引擎向公益机构捐赠多款技术产品

5月18日,字节跳动公益联合火山引擎举办了“科技应用创新让公益更美好”线上交流会,与中国红十字基金会、壹基金等多家公益机构探讨如何利用科技信息化产品提升公益事业的效率,从而进一步解决社会问题。 交流会上,火山引擎联合Pic…

云效发布策略指南|滚动、分批、灰度怎么选?

简介:在日常和用户交流过程中,我们也经常会被用户问到关于发布的问题,比如不同职能团队之间应该如何配合、发布的最佳实践应该是什么样子的等等。今天我们就来聊聊常见应用发布方式的选择,以及每种发布模式适合什么样的场景。 无论…

shell安装mysql5.7_一键部署----shell脚本安装MySQL5.7

运维开发网 https://www.qedev.com2020-11-09 12:30出处:51CTO作者:wx5ddda4c97f426一键部署----shell脚本安装MySQL5.7#/bin/bashyum-yinstallncursesbisoncmakegccgcc-cncurses-develuseraddmysql-s/sbin/nologinread-p"输入你存放压缩包的绝对路…

极致用云,数智护航

简介:我们邀请到了阿里云混合云监控平台(Sunfire)团队负责人王肇刚来给我们分析下阿里背后的数字化业务运维安全工程标准及解决方案。 本次分享涵盖了全新发布的数字化业务运维安全工程标准、安全生产解决方案,以及全新升级的产品能力:包括了…

Lakehouse 架构解析与云上实践

简介:本文整理自 DataFunCon 2021大会上,阿里云数据湖构建云产品研发陈鑫伟的分享,主要介绍了 Lakehouse 的架构解析与云上实践。 作者简介:陈鑫伟(花名熙康),阿里云开源大数据-数据湖构建云产品…

菜鸟教程 mysql like_MySQL LIKE 子句

MySQL LIKE 子句我们知道在 MySQL 中使用 SQL SELECT 命令来读取数据,同时我们可以在 SELECT 语句中使用 WHERE 子句来获取指定的记录。WHERE 子句中可以使用等号 来设定获取数据的条件,如 "runoob_author RUNOOB.COM"。但是有时候我们需要获…

云原生 Serverless Database 使用体验

简介:表格存储 Tablestore 作为一款广泛应用 Serverless DataBase,能够提供经济的计费模式,可以大幅缩减业务成本的同时, 具备极致的弹性服务能力和完全零运维的特性,能够给用户带来更丝滑的使用体验。 作者 | 李欣 …