Rings‘ Power,性能“世界第一”的Web I/O框架

2023-11-15

UringNet设计的思路和参考

在2019年,从Linux内核5.1开始,引入了io_uring这样的异步框架,io_uring的设计非常精巧,经过验证,其性能极其强悍,在文件读写的领域已经证明了其巨大的价值。很多数据库系统的底层已经引入并采用了io_uring这个组件。其文件读写性能远远超过了原来Linux中的AIO异步接口。下图是io_uring的4k顺序读和写与AIO顺序读写的性能差异。

不过很长一段时间,io_uring一直被认为只是在文件读写这种不需要缓存的场景下有非常优秀的表现。而且,在相当长的一段时间内,还没有公开发布真正用io_uring实现,并且能够大幅领先目前以select/epoll接口为基础基于reactor模式的网络I/O框架。从经验上判断,通过内核态环形缓存的方式去发送和接收I/O事件的方式理论上肯定是要比传统的不断调用epoll系统调用的性能要优秀。经过反复验证,觉得目前io_uring 网络I/O的瓶颈应该还是出在并发性上面。大多数时候,一个io_uring实例只会占用一个CPU内,要加速带有缓存的I/O,那么多线程肯定是必选项,因为I/O访问中有大量的时间是用在等待缓存的读写和拷贝,以及网络传输延迟上面了。这些系统等待时间肯定应该用其他的线程/进程进行填补。

io_uring对于I/O类型分为两种,分别叫bounded I/Ounbounded I/O这两种类型。其实,bounded I/O就是指的读写时间是有一个固定的时间范围的输入和输出方式,比如文件读写和块设备的输入输出。unbounded I/O指的是像网络socket通信这样的不确定性比较大的输入和输出方式。网络socket通信每次的读写完成的时间不确定,甚至最后无法完成。

By default, io_uring limits the unbounded workers created to the maximum processor count set by  RLIMIT_NPROC and the bounded workers is a function of the SQ ring size and the number of CPUs in the system.

io_uring的文档中提到,如果是unbounded情况下,最大的I/O并发数由RLIMIT_NPROC这个系统参数设定。而在bounded这种情况下的并发数量是由SQ ring的大小和CPU数量决定的。

对于我们比较关心的网络I/O的情况,具体是怎样的呢?事实上,socket I/O默认是采用的Non-block方式,也就是传统的Epoll这样的模式处理,在这种情况下,io_uring本质上还是进行的epoll操作。为了能够在网络I/O中采用异步多线程模式,我们必须强制网络请求通过block的方式,也就是阻塞模式进行访问。在创建和提交SQ的时候,可以加入IOSQE_ASYNC参数,这样就会通过线程池处理每个请求了。这样的I/O性能实际测试下来还是比epoll的模式稍差一些的。同时和普通模式下的io_uring的网络I/O相比,CPU的占用率也没有显著的改善。因此这种模式在网络I/O应用显得比较鸡肋。

对于epoll模式,单纯的提高并发数量并不能有效地提升IO性能,尤其像io_uring这样已经将系统调用频次降低到了相当少的程度。在我自己的虚拟机环境种,通过采用wrk的http压测,两个线程,两个io_uring实例的情况下,就几乎已经达到压测的极限性能。再增加线程和实例反而由于线程调度的消耗,最高性能还会下降。不过,经过验证,适当地增加并发运行的io_uring实例可以大大提升整体性能。在echo server压力测试的场景种,几乎能够达到目前最快的基于epoll框架的两倍的性能,而在http server的压力测试下,经过调试的框架可以至少领先基于epoll的框架20%以上,同时平均响应延迟以及延迟时间的标准差都要好于目前各类Web I/O框架。

除了并行,还有两种可以大大提高基于io_uring网络框架性能的方式,其中一个是用io_ring提供的内核态用户态共享的buffer机制。可以通过IORING_OP_PROVIDE_BUFFERS这个操作,分配内核+用户态共享的缓存,避免了socket数据读取时,内核空间到用户空间的拷贝所造成的系统开销。另外一个提高性能的方式是可以在创建io_uring的时候加入IORING_SETUP_SQPOLL参数,这样io_uring就会开启自动SQ提交模式,我们可以不需要通过每次调用内核的enter方法来提交SQ,大大加快了IO事件的处理速度。经过测试,大约能获得10%-20%的性能提升。不过这种自动提交模式也有一定的副作用,那就是会大大增加CPU的占用率,在响应网络I/O请求时,一个io_uring实例会将一个CPU核心的占用率拉到100%,而且在有I/O访问的整个时间段内,会持续高CPU占用率,同时CPU占用率和访问压力无关。总之,尽管IORING_SETUP_SQPOLL这个参数可以提高性能,但是需要慎用。只有在追求极限性能得时候可以尝试。

后面就不做过多得介绍了,我们直接上对比测试结果。目前这个框架正在开发和完善中,在近期将会公布出来。项目主要语言是Golang写,所以几个对标的网络框架也都是Golang语言的。主要比较的框架有gnet,原生net库,以及fasthttp。

Echo 压力测试结果

用于Echo压力测试的工具是rust echo bench

测试环境:

主机:
CPU:Intel Core i5 12400F 6 core 12 thread
Memory: DDR4 32GB
OS:Windows 11
测试虚拟机:
VMware® Workstation 16 Pro
Processors: 8P ; Memory 16GB; 开启硬件虚拟化支持Intel VT-x
OS:Ubuntu 22.04.1 LTS, Kernel:5.19.3

echo压力测试最终测试结果统计

echo压力测试最终测试结果统计

echo测试结论:

我们看到,在简单的echo压力测试种,采用了io_uring技术的UringNet展现出了异常强悍的基础性能,在UringNet+SQPoll开启的情况下能够达到现有高性能框架的150%~200%性能。尤其是在500连接数和512bytes测试中领先了一倍。总体来说,在对传统epoll模式框架下的web I/O形成了碾压性的性能优势

各测试项结果

测试1:连接数-500,收发包大小-512 bytes

连接数-500,收发包大小-512 bytes

测试2:连接数-1000,收发包大小-512 bytes

连接数-1000,收发包大小-512 bytes

测试3:连接数-1000,收发包大小-1024 bytes

连接数-1000,收发包大小-1024 bytes

HTTP压力测试

HTTP压力测试,采用了比较常用的wrk压测工具。压测环境为:

主机:
CPU:Intel Core i5 12400F 6 core 12 thread
Memory: DDR4 32GB
OS:Windows 11
被测程序虚拟机:
VMware® Workstation 16 Pro
Processors: 8P ; Memory 16GB; 开启硬件虚拟化支持Intel VT-x
OS:Ubuntu 22.04.1 LTS, Kernel:5.19.3
wrk运行的虚拟机:
VMware® Workstation 16 Pro
Processors: 4P ; Memory 8GB; 开启硬件虚拟化支持Intel VT-x
OS:Ubuntu 20.04.5 LTS, Kernel:5.15.0

HTTP压力测试结果统计

HTTP压力测试结果统计

HTTP测试结论:

我们看到,在简单的HTTP压力测试中,和其他的框架相比,在http测试中UringNet仍然保持者比较明显的优势,尤其是在连接数在200的情况下,由于测试是在同一台主机上运行,测试程序和被测试程序都运行在同一台宿主机的桌面虚拟机中,因此在多线程,高并发下实际上对被测试程序的结果有些影响。另外由于缓存部分优化没有现有的框架这么完善,因此优势看上去和没有echo测试那么巨大。

另外,在所有的测试对比中,UringNet的响应能力明显占优,在响应延迟上和响应时间和每秒响应数量的正态偏离指标上也有不少亮点。这说明以io_uring为基础的网络I/O框架也有比较良好的稳定性和一致性。

各测试项结果

测试1:连接数-200,线程数-4

FastHttp

FastHttp

Gnet:

Gnet

UringNet:

UringNet

测试2:连接数-200,线程数-2

FastHttp

FastHttp

Gnet:

Gnet

UringNet:

UringNet

测试3:连接数-400,线程数-4

FastHttp

FastHttp

Gnet:

Gnet

UringNet:

UringNet

测试4:连接数-400,线程数-2

FastHttp

FastHttp

Gnet:

Gnet

UringNet:

UringNet

测试5:连接数-600,线程数-4

FastHttp

FastHttp

Gnet:

Gnet

UringNet:

UringNet

测试6:连接数-600,线程数-2

FastHttp

FastHttp

Gnet:

Gnet

UringNet:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rings‘ Power,性能“世界第一”的Web I/O框架 的相关文章

  • Docker 容器可以访问 DNS,但无法解析主机

    我在运行 docker 容器时遇到一个有趣的问题 突然间 我无法从容器内解析 DNS 这是一个概要 一切都没有解决 apt get pip 一次性 ping 容器等正在运行docker run it dns 8 8 8 8 ubuntu p
  • Tk 初始化失败:无显示名称且无 $DISPLAY 环境变量

    我试图从 Ubuntu 终端调用 Centos 服务器上的工具 我收到以下错误 Tk 初始化失败 没有显示名称 也没有 DISPLAY 环境变量 请帮我解决这个问题 提前致谢 连接到你的 CentOS 机器ssh Y其中 每man ssh
  • mod_perl 无法看到 /tmp 中的文件

    我有一些 mod perl 代码试图访问 tmp 下的文件 但它抛出 没有这样的文件或目录 错误 我在代码中添加了一个 ls al tmp 来查看 Perl 在目录中看到的内容 它只给了我 和 drwxrwxrwt 2 root root
  • 警告构建使用导出符号的内核模块

    我有两个内核模块 例如 modA 和 modB modA 导出一个符号EXPORT SYMBOL symA modB 使用它 我有标题modA h对于modA extern void symA int param and in modB c
  • 如何使用 shell 脚本解压所有 .tar.gz?

    我试过这个 DIR path tar gz if ls A DIR 2 gt dev null then echo not gz else tar zxvf path tar gz C path tar fi 如果该文件夹有一个 tar 则
  • 如何将字符串推送到标准输入?在启动时通过 stdin 提供输入,然后以交互方式读取 stdin 输入 [重复]

    这个问题在这里已经有答案了 有没有办法在调用程序时将字符串 推送 到程序的标准输入流 这样我们就可以达到这样的效果 echo something my program 但不是在之后读取 EOF something my program将从原
  • 使用 xargs 时如何获取退出代码(并行)

    我制作了一个用于启动并行 rsync 进程的脚本 bin bash LIST 1 DEST DIR 2 RSYNC OPTS 3 echo rsyncing From SRC DIR To DEST DIR RSYNC OPTS RSYNC
  • Git - 致命:无法获取当前工作目录?

    When I git clone从回购协议中 我得到 fatal Could not get current working directory No such file or directory 我该怎么办 我检查了服务器并发现 git文
  • 多线程进程的线程ID可以与另一个正在运行的进程的进程ID相同吗?

    我正在尝试找到一种方法来唯一标识多进程环境中的线程 我有一个服务器 它跟踪连接到它的不同进程 其中一些是多线程的 一些不是 为了识别多线程连接中的线程 我使用线程 ID 作为唯一标识符 在任何给定时间最多有 1 个多线程进程连接 我的问题是
  • Pthread互斥锁由不同线程解锁

    一个天真的问题 我之前读到过 MUTEX 只能由锁定它的线程解锁 但我写了一个程序THREAD1锁定 mutexVar 并进入睡眠状态 然后THREAD2可以直接解锁mutexVar做一些操作并返回 gt 我知道每个人都说我为什么要这样做
  • 串口读取未完成

    下面的函数用于在Linux下从串口读取数据 我在调试时可以读取完整的数据 但是当我启动程序时 读缓冲区似乎并不完整 我正确接收了一小部分数据 但缓冲区的其余部分完全正确zero 可能是什么问题呢 int8 t serial port ope
  • 如何使用 bash 粘贴来自单独文件的列?

    我想用分隔符 合并不同的列表 第一个列表有 2 个单词 cat first one who 第二个列表有 10000 个单词 cat second languages more simple advanced home expert tes
  • 如何每周日运行 crontab 作业

    我想弄清楚如何每周周日运行 crontab 作业 我认为以下应该可行 但我不确定我是否理解正确 下面的说法正确吗 5 8 6 这是 crontab 格式的解释 1 Entry Minute when the process will be
  • 如何在 Linux 中制作一个将文件转换为大写的 x86 汇编程序?

    我找到了一个名为 ProgrammingGroundUp 1 0 booksize pdf 的 pdf 文件 其中一个项目是制作一个汇编程序 该程序接收文件并将其转换为大写 section data CONSTANTS system cal
  • 在 Bash 中使用“$RANDOM”生成随机字符串

    我正在尝试使用 Bash 变量 RANDOM创建一个由包含整数和字母数字的变量中的 8 个字符组成的随机字符串 例如 var abcd1234ABCD 我怎样才能做到这一点 使用参数扩展 chars 是可能的字符数 是模运算符 chars
  • 如何在 .zip 文件中使用 grep

    有 3 个文件 a csv b csv c csv 压缩为 abh zip 现在可以在 abh zip 上执行 grep 命令 是否有任何通配符 仅对里面的 c csv 文件运行 grep压缩 如果你有zipgrep 据我所知 它是随zip
  • 如何使用 sed 交换两行?

    有谁知道如何更换line a with line b and line b with line a使用 sed 编辑器在文本文件中 我可以看到如何用保留空间中的一行替换模式空间中的一行 即 Paco x or Paco g 但是如果我想采取
  • 将 file.lib 构建为可在 linux 上使用的 file.a

    我正在尝试将 api 从 Windows 移植到 Linux 到目前为止 我已经完成了 file cpp 和 file h 的工作 但我仍然有一个指定给 Windows 的库 lib 这是 api 工作所必需的 我怎样才能从这个库构建一个可
  • 在 Windows 下对 Unix 下创建的文件使用 fstream::seekg

    我有一个C 跨平台程序 在Linux下用g 编译 在PC下用Visual Studio编译 该程序将行写入文本文件 使用 lt lt 运算符和std endl 但也可以从生成的文本文件中读回数据 使用std getline 为了优化数据访问
  • 设置 nginx 具有多个 IP

    我的 nginx 配置文件位于 etc nginx sites available 下 有两个上游说 upstream test1 server 1 1 1 1 50 server 1 1 1 2 50 upstream test2 ser

随机推荐

  • 学深度学习可以做什么?可以从事什么工作?

    学习深度学习可以让您涉足人工智能领域的前沿 为各种领域带来巨大的创新和改进机会 深度学习的核心思想是通过多层神经网络模拟人类大脑的工作方式 从而实现对复杂数据的高级处理和理解 这为以下方面的应用提供了广泛的可能性 学深度学习可以做什么 首先
  • 分布式爬虫学习笔记

    安装python 虚拟环境 将使用python2 3的项目分开 1 安装virtualenvcmd cmd命令 pip install virtualenv 2 因为下载开发包很慢 所以下载开发包的第三方镜像 python豆瓣源 百度 安装
  • 精品,全网最详细-软件测试技术自动化测试总结,最屌详解看了默默卷起来

    目录 导读 一 自动化测试 二 自动化测试的意义 三 手工测试的局限性 四 自动化测试带来的好处 五 自动化测试的前提条件 1 需求变动不频繁 2 项目周期足够长 3 自动化测试脚本可重复使用 4 手工测试无法完成 六 自动化测试的方法 七
  • 使用Python编写一个多线程的12306抢票程序

    国庆长假即将到来 大家纷纷计划着自己的旅行行程 然而 对于很多人来说 抢购火车票人们成了一个令人头疼的问题 12306网站的服务器经常因为流量高而崩溃 导致抢票变得越来越严重异常困难 首先 让我们来了解一下12306抢票的难点 由于很多人都
  • 程序员的职级和薪酬体系

    今天我们要讨论一个程序员都关心的话题 学了程序到底能赚多少钱 老有人问学程序到底有没有前途 我应该是学前端呢 还是应该学大数据 程序员百万年薪到底有多难 其实 这些问题抛开兴趣的本质都在问一个问题 当了程序员能赚多少钱 我相信广大程序员的力
  • MYSQL lag()和lead()函数用法

    这两个函数是偏移量函数 可以查出一个字段的前面N个值或者后面N个值 配合over来使用 下面举例说明 新建表格如下 drop table if exists exam record CREATE TABLE exam record id i
  • Python——beautiful,requests,歌单(多线程)

    目录 一 定义三个函数方便之后调用 1 由url获取soup函数 2 传入soup 进具体信息进行解析 3 由图片链接保存到本地 二 生产 消费主模块 精华部分 1 获取一个分类下的所有歌单的id 相当于生产者 2 对每个id 获取歌单的详
  • 从零开始学习OpenWrt完美教程

    Cisco Linksys在2003年发布了WRT54G这款无线路由器 同年有人发现它的OS是基于Linux的 然而Linux是基于GPL许可证发布的 按照该许可证Cisco应该把WRT54G 的OS的源代码公开 2003年3月 Cisco
  • qt将字符串转换为16进制数(hex)

    1 参考博客 https www cnblogs com ramlife p 11858896 html 2 这个问题就是类似与将 10 转换为0x10 或者是 1B 转换为0x1B 代码如下 QString str 0x1B int va
  • nginx优化篇之Linux 内核参数的优化

    由于默认的Linux内核参数考虑的是最通用的场景 这明显不符合用于支持高并发访问的Web服务器的定义 所以需要修改Linux内核参数 使得Nginx可以拥有更高的性能 在优化内核时 可以做的事件很多 不过 我们通常会根据业务特点来进行调整
  • vue input框带搜索功能

    vue input框带搜索功能 Input输入框
  • C语言编程题

    公鸡5文钱一只 母鸡3文钱一只 小鸡3只一文钱 用100文钱买一百只鸡 问公鸡 母鸡 小鸡要买多少只刚好凑足100文钱 我们都知道 我们一般用穷值法 在for循环求多个符合条件的解 公鸡最多 100 5 20只 母鸡最多 100 3 33只
  • C语言—总结3—指针,指针与数组的关系,结构体指针,数组指针,指针数组,函数指针

    一 指针 1 定义 地址的别名 int a 1 int p a 指针p指向了a的地址 p里保存了a的地址 2 分析说明 int p 这是一个普通的整型变量 int p 首先从P 处开始 先与 结合 所以说明P 是一个指针 然后再与int 结
  • 计算机c盘拒绝访问怎么办,在线等电脑高手!我把c盘访问权限删了。c盘拒绝访问怎么处理...

    oWorkingDirectoryrunas HKEY CLASSES ROOT IsolatedCommand exe runas exefile 管理员取得所有权 exe icacls t icacls 1 reg 管理员取得所有权 I
  • 如何看待 TechEmpower Web Frame Benchmark Round 18 的结果?

    https www zhihu com search type content q web 20framework 20benchmark
  • 找不到本地组策略编辑器找不到gpedit.msc 的解决方法

    通常打开本地组策略编辑器 只需要 win R 在运行里输入 gpedit msc 就可以打开 但是 在windows 家庭版和学生版里 会提示找不到路径 可以用以下办法解决 新建一个文本文档 名字随便取 编辑以下批处理内容 保存后将后缀名改
  • 2020/09/28 轮播react-slick报错 can`t resolve ‘react-slick‘

    报错 前提 我已经按照官网安装好了 npm install react slick save npm install slick carousel save 并且引入了css样式 import slick carousel slick sl
  • 强化学习(Reinforcement Learning)知识整理

    马尔可夫决策过程 Markov Decision Processes MDPs MDPs 简单说就是一个智能体 Agent 采取行动 Action 从而改变自己的状态 State 获得奖励 Reward 与环境 Environment 发生
  • 数字IC手撕代码-有限状态机FSM-饮料机

    前言 本专栏旨在记录高频笔面试手撕代码题 以备数字前端秋招 本专栏所有文章提供原理分析 代码及波形 所有代码均经过本人验证 目录如下 1 数字IC手撕代码 分频器 任意偶数分频 2 数字IC手撕代码 分频器 任意奇数分频 3 数字IC手撕代
  • Rings‘ Power,性能“世界第一”的Web I/O框架

    UringNet设计的思路和参考 在2019年 从Linux内核5 1开始 引入了io uring这样的异步框架 io uring的设计非常精巧 经过验证 其性能极其强悍 在文件读写的领域已经证明了其巨大的价值 很多数据库系统的底层已经引入