Monoio 性能测试实践:thread-per-core 的 io_uring 运行时与 Tokio、Glommio 的吞吐、延迟和 CPU 开销对比 语言运行时后端网络【免费下载链接】monoioRust async runtime based on io-uring.项目地址https://gitcode.com/gh_mirrors/mon/monoio点击查看免费下载本文基于 Monoio 官方的性能测试报告docs/en/benchmark.md完整还原其压测环境、两类测试方法极限性能测试与固定压力测试以及全部关键结论并结合仓库中 raw_data.txt 的原始压测数据和monoio源码解释这些数字背后的 thread-per-core 调度模型与 io_uring 驱动实现帮助读者理解 io_uring 异步运行时在横向扩展性、延迟和 CPU 消耗上的工程权衡。测试目标与选型为了衡量 Monoio 的性能表现官方选取了两个具有代表性的 Rust 异步运行时作为对照组Tokio基于 epoll 类机制的工作窃取运行时和 Glommio同样基于 io_uring 的运行时。关于三者机制差异的背景可参考 Comparing with OthersMio/Tokio 使用 epoll/kqueue 这类观察 fd 就绪事件、随后自行读写的机制每次就绪仍需完成一次用户态-内核态切换而 Glommio 与 Monoio 都是 io_uring 路线Monoio 的差异点在于它不运行在其他运行时之上、并采用 thread-per-core 模型详见 README.md 的 Design Goal 一节。测试环境压测在字节跳动生产网上进行发压端client与被压端server运行在不同的物理机上。被压端配置如下Intel(R) Xeon(R) Gold 5118 CPU 2.30GHzEthernet controller: Intel Corporation Ethernet Controller X710 for 10GbE SFP (rev 02)Linux 5.15.4-arch1-1 #1 SMP PREEMPT Sun, 21 Nov 2021 21:34:33 0000 x86_64 GNU/Linuxrust nightly-2021-11-26两个适用前提需要注意内核版本Monoio 走 io_uring 驱动要求 Linux 5.6本环境为 5.15满足要求见 Platform Support。低版本内核可退回 legacy 驱动epoll/kqueue但那是另一条性能基线见 Use Legacy Driver。memlock 限制io_uring 需要用户态/内核态共享内存提交/完成队列环、注册缓冲区等内核默认的 memlock 上限常见为 64 KiB过小会导致运行时无法正常工作需按 Set memlock limit 的说明用ulimit -l检查并调大否则可能出现code: 105, kind: Uncategorized, message: No buffer space available之类的读写出错。测试工具压测工具本身使用 Rust 基于 Monoio 开发其源码位于monoio-rs/monoio-benchmark仓库仓库名见原文档引用。这保证了三个运行时在发压侧使用同一工具、同一客户端逻辑压测差异主要来自服务端运行时本身。需要说明的是该组数据产生于 2021 年的 nightly 工具链与 5.15 内核环境可视为 Monoio 的历史基准当前仓库中 monoio 版本已演进见 monoio/Cargo.toml 中的version 0.2.4复测时应以当前版本与当前环境为准。测试一极限性能测试探测系统峰值测试方法在客户端启动固定数量的连接逐步增加连接数使服务端负荷持续升高直到 QPS 不再增长。连接数越多服务端负荷越高本测试旨在探测系统的极限性能峰值 QPS。原始逐点数据client-nCore * client-conn-per-core → real-QPS, latency格式完整保存在 raw_data.txt 中。以 1K 消息、服务端 1 核、客户端 4 核的组别为例连接数/核Tokio Server 1CGlommio Server 1CMonoio Server 1C4C × 80136003, 2351 us134051, 2408 us134243, 2414 us4C × 130193845, 2679 us156560, 3329 us208272, 2494 us4C × 150189423, 3194 us156228, 3843 us221444, 2706 us4C × 170186446, 3626 us156098, 4358 us214008, 3173 us峰值 QPS 汇总100B 消息raw_data.txt中专门汇总了 100B 消息下每个核数档位的最佳 QPS100B Best QPS段。之所以选 100B 而非 1K是因为1K 会在核数较多时打满网卡而 100B 能让瓶颈留在 CPU/运行时一侧服务端核数TokioGlommioMonoio1C205,726163,709232,8882C228,719317,929442,2574C430,921616,687868,5258C774,5261,116,1161,588,52812C892,6011,616,3052,194,58816C908,1792,064,5892,764,15220C835,9832,441,9363,232,227从这张表可以直接验证原文档的三个结论单核且连接数极少时Monoio 延迟略高于 Tokio吞吐随之略低。原文归因于 io_uring 与 epoll 的机制差异io_uring 提交/完成路径的固有开销在小批量短请求上相对 epoll 的就绪通知存在延迟差。4 核时 Monoio 峰值约为 Tokio 的 2 倍868,525 / 430,921 ≈ 2.0×16 核时接近 3 倍2,764,152 / 908,179 ≈ 3.0×与文档文字描述一致。Tokio 的峰值在核数增多后几乎不增长甚至回落8C → 16C 仅从 774,526 增至 908,17920C 反而降到 835,983表现为单 Core 的平均峰值性能随核数增加而下降Monoio 与 Glommio 则基本保持线性扩展。Glommio 与 Monoio 同为 io_uring thread-per-core 模型扩展性相近但各档位峰值仍低于 Monoio如 16C2,064,589 vs 2,764,152。测试二固定压力测试恒定 QPS 下的延迟与 CPU测试方法生产环境中打满服务端并不现实因此第二类测试在恒定压力下观察运行时的表现给客户端每一核设置 QPS 上限client-QPS-limit-per-core固定 CPU 频率 3200MHz记录实际 QPS、延迟以及 CPU 占用userkern 与 user。原始数据摘自 raw_data.txt场景 A1 核服务端1K 消息250 连接/核客户端压力TokioGlommioMonoio4C × 40000160000, 5595 us, 89.0%151125, 6631 us, 100.0%160000, 4911 us, 78.1%4C × 50000179992, 5563 us, 100.0%150802, 6640 us, 100.0%200000, 4873 us, 97.4%4C × 60000179833, 5568 us, 100.0%151019, 6641 us, 100.0%210040, 4769 us, 100.0%场景 B1 核服务端1K 消息80 连接/核低连接数客户端压力TokioGlommioMonoio4C × 400016000, 2553 us, 8.7%16000, 2770 us, 13.0%16000, 2856 us, 7.3%4C × 1200048000, 2426 us, 28.7%48000, 2503 us, 34.6%48000, 2657 us, 24.5%4C × 2400096000, 2385 us, 53.5%96000, 2447 us, 62.1%96000, 2569 us, 46.9%场景 C4 核服务端1K 消息250 连接/核客户端压力TokioGlommioMonoio16C × 24000384000, 9470 us, 389.6%384000, 6166 us, 321.6%384000, 4875 us, 232.0%16C × 30000423771, 3042 us*, 397.2%480000, 7648 us, 379.2%480000, 5340 us, 284.0%16C × 42000407282, 9701 us, 400.0%518723, 7740 us, 400.0%672000, 5599 us, 381.2%* 原始数据文件在该段标注了 Now the network becomes unstable... The latency may not accurate.即 4C×80Conn 组的部分延迟数值受网络抖动影响解读时以 CPU 列更可靠。结论连接数较少时Tokio 相对基于 uring 的 Glommio 和 Monoio 有延迟优势场景 B 中 2553 us 对 2856 us这与极限测试中单核少量连接 io_uring 延迟偏高的结论相互印证但即使在最低压力档Monoio 的 CPU 消耗仍是三者最低7.3% vs 8.7% vs 13.0%。随着连接数与压力上升Monoio 的延迟和 CPU 占用都变成最低场景 C 的最高压力档下Monoio 以 381.2% CPU 完成 672000 QPS而 Tokio 用满 400% CPU 只能到 407282 QPSGlommio 到 518723 QPS。原文档的总结是随着连接数的上涨Monoio 在延迟和 CPU 占用上都是最低的。源码视角这些差异从何而来理解了测试方法后结合仓库源码可以看出 Monoio 数字背后的结构性原因。thread-per-core数据不跨线程省去迁移与同步开销README.md 的 Design Goal 指出Monoio 面向以网络 socket IO 为主的服务器场景采用 thread-per-core 模型任务不需要Send/Sync线程本地数据不会在 await 点逃逸到其他线程。从源码结构看这一点落在 monoio/src/runtime.rs 的Context上每个线程持有独立的TaskQueue本地运行队列与thread_idDEFAULT_CTX通过thread_local!按线程隔离跨线程唤醒依赖 monoio/src/driver/mod.rs 中unpark机制Uring 驱动下注册 eventfd flume 通道见 monoio/src/driver/uring/mod.rs 中new_with_entries里创建 eventfd 并注册EventWaker的逻辑。没有跨线程任务迁移就意味着没有工作窃取运行时的任务队列锁竞争与 cache line 迁移——这是极限测试中核数越多、相对 Tokio 优势越大的结构性解释之一。同时README.md 的 Limitations 一节给出了反向边界也应如实告知读者If the workload is very unbalanced, it may cause performance degradation than Tokio since CPU cores may not be fully utilized.即负载严重不均时固定核绑定的 thread-per-core 模型可能无法吃满 CPU这是该模型固有的取舍。驱动与环大小entries、memlock 与性能的关联两个驱动实现共享 monoio/src/driver/mod.rs 中的Drivertraitsubmit/park/park_timeout。io_uring 侧的默认环大小定义在 monoio/src/driver/uring/mod.rs 的IoUringDriver::DEFAULT_ENTRIES: u32 1024构建入口 monoio/src/builder.rs 提供RuntimeBuilder::with_entries最小 256见MIN_ENTRIES常量与uring_builder用于替换底层io_uring::Builder。这与 Set memlock limit 文档直接呼应memlock 设置 512 一般够用高吞吐场景建议调大或 unlimited并在创建运行时时用with_entries指定更大的环条目数以获得更好性能——环大小同时决定了共享内存占用和单批可提交/可完成的 IO 操作数是压测调参时的重要变量。完整构建示例见 examples/builder.rslet mut rt monoio::RuntimeBuilder::monoio::FusionDriver::new() .with_entries(256) // 最小值 256默认 1024 .enable_timer() .build() .unwrap(); rt.block_on(async { /* ... */ });此外从 monoio/Cargo.toml 的 features 可见若干与 IO 路径性能相关的开关例如zero-copy启用SOCK_ZEROCOPY MSG_ZEROCOPY注释中明确警告可能导致性能退化、splice需内核 5.7等复现压测时应与官方测试保持一致的 feature 组合否则数字不可比。如何复现与验证环境准备Linux 5.6 内核用ulimit -l确认 memlock必要时按 docs/en/memlock.md 修改/etc/security/limits.conf* hard memlock unlimited/* soft memlock unlimited或在 systemd 中设置LimitMEMLOCK。压测工具使用官方monoio-rs/monoio-benchmark仓库中的工具客户端与服务端分机部署逐档增加每核连接数/每核 QPS 上限。对照组在相同环境下分别跑 Tokiomulti-thread epoll与 Glommioio_uring服务端保持消息大小、CPU 频率固定如 3200MHz、网卡不打满用 100B 消息测横向扩展用 1K 消息测连接扩展。数据解读对照 raw_data.txt 的格式记录real-QPS, latency, cpu(userkern)重点看三个量——峰值 QPS 的核数线性度、恒定压力下的延迟/CPU 比、以及低连接数下的延迟差。中文版的同一份测试报告位于 docs/zh/benchmark.md可对照阅读。需要再次强调的前提以上所有数字都是特定硬件Xeon Gold 5118 10GbE、特定内核5.15与特定工具链版本下的历史测量结果用于说明机制层面的相对行为趋势在你自己的环境里绝对值会有差异io_uring 路线在小批量请求上延迟偏高、大规模连接下 CPU 效率与横向扩展性占优这一相对关系才有参考意义。赞分享语言运行时后端网络【免费下载链接】monoioRust async runtime based on io-uring.项目地址https://gitcode.com/gh_mirrors/mon/monoio点击查看免费下载相关推荐monoio基于 io_uring/epoll/kqueue 的 thread-per-core Rust 异步运行时实战指南monoio基于 io_uring/epoll/kqueue 的 thread per core Rust 异步运行时实战指南 Monoio 是一个采用 th语言运行时后端网络如何快速上手layoutFlutter响应式布局开发新手入门指南如何快速上手layoutFlutter响应式布局开发新手入门指南 layout是一款专为Flutter开发者打造的响应式布局开发工具能够帮助开发者轻松创建适人工智能AI AgentAgent 沙箱云原生容器运行时零信任PDF补丁丁完整指南免费快速解决PDF书签、页面与限制难题的终极方案PDF补丁丁完整指南免费快速解决PDF书签、页面与限制难题的终极方案 办公桌上堆着十几份页面大小不一、没有书签、还带着打印限制的PDF文件想统一整理却找不到桌面应用文档上一篇如何快速批量下载微博图片weiboPicDownloader的完整使用指南下一篇物理AI新纪元Cosmos3-Super-Image2Video在机器人与自动驾驶中的革命性应用 创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考