语言运行时后端网络【免费下载链接】monoioRust async runtime based on io-uring.项目地址https://gitcode.com/gh_mirrors/mon/monoio点击查看免费下载本篇指南基于 monoio 官方文档 Comparing with Others围绕“同为 Rust 异步运行时Monoio 与 Mio/Tokio、Tokio-uring、Glommio 的差别究竟在哪”展开。读完本文你将理解 epoll/kqueue 与 io_uring 两类 IO 机制的本质差异、各运行时在兼容性上的不同取舍以及 Monoio 在多线程场景下的性能表现并据此判断自己的业务场景适合哪种运行时。一、为什么 IO 机制的选择是差异的根源Rust 生态中存在大量异步运行时runtimeMonoio 的定位在 README 中写得很明确它是一个thread-per-core模型、以 io_uring/epoll/kqueue 为底层驱动的原生异步运行时。各运行时之间最核心的分歧点只有一个底层使用哪种 IO 机制。epoll/kqueue 的工作方式Mio 和 Tokio 不使用 io-uring而是使用 epoll 类机制。官方文档对这一机制的解释是Epoll/kqueue 是一种允许程序监视多个文件描述符fd事件的机制它的设计目的是“观察哪个 fd 就绪可读/可写”但真正的 read/write 需要你自己后续去发起——这意味着更多的用户态/内核态上下文切换。可以把它概括为一个两步流程epoll_wait/kevent返回“哪个 fd 就绪”用户态再对该 fd 发起read/write系统调用数据才真正拷贝完成。也就是说每次 IO 至少涉及“等待就绪”和“执行传输”两次内核交互。这正是文档中 “more context switching between user space and kernel space” 的含义。io_uring 的工作方式io_uring 则将“提交请求”和“收割结果”统一为一对用户态/内核态共享的提交队列SQ与完成队列CQE一次系统调用即可批量提交或批量收割数据拷贝与就绪通知合并在异步 IO 完成中完成。Monoio 的 io_uring 驱动实现位于 IoUringDriver它基于io-uringcrate 直接持有IoUring实例驱动核心逻辑收敛在 Driver trait 定义的submit/park/park_timeout三个方法上提交操作到内核并处理返回事件、阻塞等待并处理事件、带超时的等待。Monoio 同时保留了第二套驱动LegacyDriver 基于mio的Poll即 epoll/kqueue实现用于内核不支持 io_uring 的环境见 平台支持 与 Legacy driver 文档。在 Cargo.toml 中两者对应iouring与legacy两个 feature默认同时开启运行时通过FusionDriver动态探测选择。二、Mio 和 Tokioepoll 路线的成熟方案官方文档对 Mio 与 Tokio 的定位是Mio是一个跨平台的 epoll/kqueue/IOCP 封装库负责在不同操作系统上提供统一的事件驱动接口Tokio构建在 mio 之上提供异步 IO 与跨线程调度work-stealing支持适合绝大多数通用应用与部署环境。从源码结构看Monoio 对这条路线并非陌生它的 legacy 驱动直接依赖mio 0.8Cargo.toml 依赖声明LegacyInner内部就持有mio::Poll与mio::EventsWindows 上则复用 IOCP 封装。可以说Monoio 的兼容模式本质上就是“Tokio 同款”的 epoll 路径。两条路线的深层区别在于调度模型维度Tokiowork-stealingMonoiothread-per-core任务调度任务可在多个工作线程间迁移要求任务Send任务固定在所属线程无需Send/Sync可安全使用 thread-local本地数据跨线程共享需Arc等可直接使用 thread local storage负载不均时自动再均衡某些核心可能闲置性能可能下降README Limitations 第 2 条明确指出因此官方文档的结论是“Tokio 适合大部分通用应用与环境”这句话本身就是一种设计取舍的承认——通用性换掉了极致路径而 Monoio 则反向选择了牺牲通用性thread-per-core buffer 所有权接口来换取 IO 吞吐。三、Tokio-uring兼容性与效率之间的妥协官方文档对 Tokio-uring 的评述有两点接口形态Tokio-uring 管理 fd并提供了以 buffer 所有权为参数的 IO 接口——这是 io_uring 异步 IO 的天然要求通知机制它仍然用 epoll 来接收 uring fd 的就绪通知官方认为这一步 “is not necessary”并非必要。但因为 Tokio-uring 复用了 Tokio 的大部分能力所以它被视为一个面向兼容性的妥协方案。为什么 io_uring 接口要求 buffer 所有权这一点在 为什么使用 AsyncRent 作为 IO 抽象 中有完整论证核心是两条buffer 地址必须固定io_uring 的 IO 是真正异步的请求提交给内核后内核何时读写该 buffer 不可预知提交前必须保证 buffer 在 IO 完成前地址不变且有效生命周期必须被约束若只借用 buffer/mut用户在 future 被 drop 后即可释放 buffer而内核可能仍在操作这块内存导致内存破坏。除非有 async drop否则 Rust 下不做所有权传递几乎无法保证安全。对照之下Tokio 的AsyncRead/AsyncWrite之所以只需引用是因为 epollsyscall 模式下系统调用是同步执行的一旦用户拿回控制权内核一定不在操作 buffer因此不存在悬空窗口。Monoio 原生接口AsyncReadRent::readT: IoBufMut(mut self, buf: T) - impl FutureOutput BufResultusize, T见 async_read_rent.rs正是“传入所有权、随结果一起归还 buffer”的形态。Monoio 与 Tokio-uring 的关键区别README 直接点明“Unlike Tokio-uring, Monoio does not run on top of another runtime, rendering it more efficient.” 也就是说Tokio-uring 是“寄生”在 Tokio 调度器之上的 io_uring 扩展事件通知与任务调度都要经过 Tokio 的 reactorMonoio 的 IoUringDriver 就是运行时本身的事件源submit/park直接在 CQ 上阻塞收割中间没有第二层 runtime。这是“更直接、更少的中间层”的含义也呼应了原文档中“用 epoll 通知 uring 并非必要”这一批评。四、Glommio另一个 io_uring 通用运行时官方文档对 Glommio 的评价是Glommio 是一个基于 io_uring 支持通用应用的复杂库。出于兼容性考虑Glommio 会拷贝数据官方认为这是不必要的。此外我们发现 Glommio 的部分实现不够高效。这里有两个值得展开的点“拷贝数据”是兼容性的代价。基于 buffer 所有权的原生接口与以tokio::io::AsyncRead/AsyncWrite引用式接口为中心的现有生态不兼容。要同时服务两套生态就必然存在一层转换转换的常见实现就是多一次 buffer 拷贝。Monoio 自己也面临同样的问题并且同样用兼容层解决monoio-compat 提供StreamWrapperT见 safe_wrapper.rs内部持有自有读/写 buffer默认各 8 KiB把引用式poll_read/poll_write翻译成 buffer 所有权调用代价同样是一次额外的 buffer 拷贝——这一机制在 与 Tokio 生态兼容 中有详细说明。除此之外Monoio 还提供了tokio-compat仅 legacy 驱动下实现 Tokio 接口无额外开销与poll-io在 uring 上叠加 poll 感知无拷贝两种更轻量的兼容路径。可以这样理解两者的差别Glommio 把“拷贝式兼容”内建在主路径中而 Monoio 把零拷贝的 buffer 所有权接口作为主路径把拷贝留给可选的兼容层——这与原文档对 Glommio “copies the data, which is unnecessary” 的批评是同一逻辑的一体两面。五、性能对比Monoio vs Tokio vs Glommio官方文档的结论是Monoio 在多个场景下与 Tokio、Glommio 做了对比测试虽然 benchmark 数据占优但这不代表其他运行时是“糟糕的设计”只是不同目标场景下取舍的差异。详细数据见 Performance test data and comparison。该文档给出的测试环境为客户端与服务器位于不同物理机字节跳动生产网络服务器Intel Xeon Gold 5118 2.30GHzIntel X710 10GbE 网卡系统Linux 5.15.4rust nightly-2021-11-26。极限性能测试压满服务器测试方法客户端固定连接数压测服务端连接数越多服务器负载越高。文档结论单核 极少连接Monoio 的延迟高于 Tokioio_uring 与 epoll 的机制差异所致吞吐也低于 Tokio——这是 io_uring 路径的固有短板场景其余所有场景Monoio 优于 Tokio 和 Glommio。Tokio 的单核平均峰值性能随核数增加而下降Monoio 的峰值性能横向扩展性最好具体倍数4 核时峰值约为 Tokio 的 2 倍16 核时接近 3 倍用 100 Byte 小消息消除网卡瓶颈后1K 消息在多核下会打满网卡Monoio 与 Glommio 能更好地保持线性扩展而 Tokio 在多核下提升很小甚至退化。固定压力测试模拟生产生产环境不可能把服务器压满因此固定压力下的表现同样重要如 1 核 × 80 连接、4 核 × 250 连接等组合。文档结论连接数较少时Tokio 对基于 uring 的 Glommio 与 Monoio 有延迟优势但 Monoio 的CPU 消耗仍然是最低的随着连接数增加Monoio 的延迟与 CPU 占用均成为最低。需要强调适用前提以上数据产生于 2021 年的特定硬件与内核版本属于该测试条件下的结论不应外推为任意环境下的绝对排名不同业务CPU 密集、连接数极少、负载不均衡下各运行时的优劣可能逆转。六、面向不同场景的选型小结把官方文档的比较、源码事实与 Limitations 汇总成一张决策表运行时IO 机制调度模型接口形态适用场景Mio/Tokioepoll/kqueue就绪通知 同步 syscallwork-stealing跨线程迁移引用式AsyncRead/AsyncWrite生态最全通用服务端应用负载不均或需要任务迁移Tokio-uringio_uring但 epoll 辅助通知复用 Tokiobuffer 所有权 Tokio 能力复用想在 Tokio 生态内渐进引入 io_uringGlommioio_uring单线程绑核兼容路径需数据拷贝高吞吐网络服务端Monoioio_uring主/ epoll·kqueuelegacy 兜底thread-per-core任务不迁移原生 buffer 所有权AsyncReadRent等兼容层monoio-compat/poll-io/tokio-compatIO 密集的高吞吐服务端如负载均衡器可接受 thread-per-core 约束几个基于仓库事实的实操要点内核版本io_uring 路径要求 Linux 5.6且需要正确配置 memlock见 platform-support.md、memlock.md不满足时可显式选择 legacy 驱动支持 Linux 与 macOS驱动选择不指定时默认fusion模式运行时探测、优先 io_uring也可通过#[monoio::main(driver uring | legacy | fusion)]或RuntimeBuilder::IoUringDriver显式指定详见 use-legacy-driver.md接口选型追求极致性能用原生 rent 接口参考 examples/echo.rs 的读写模式必须对接 Tokio 生态组件时按需选择零拷贝的poll-io、无开销的tokio-compat仅限 legacy或带一次拷贝的monoio-compat负载不均衡警告README 明确说明若负载非常不均衡Monoio 可能因 CPU 核心无法被充分利用而性能劣于 Tokio——thread-per-core 不是万能解选型前应先确认业务负载的分布特征。参考文档Comparing with Others本文主体文档Performance test data and comparisonPlatform Support / Use Legacy Driver / Memlock为什么使用 AsyncRent 作为 IO 抽象 / 与 Tokio 生态兼容源码driver 模块、IoUringDriver、LegacyDriver、AsyncReadRent 接口、monoio-compat 兼容层赞分享语言运行时后端网络【免费下载链接】monoioRust async runtime based on io-uring.项目地址https://gitcode.com/gh_mirrors/mon/monoio点击查看免费下载相关推荐Monoio 性能测试实践thread-per-core 的 io_uring 运行时与 Tokio、Glommio 的吞吐、延迟和 CPU 开销对比Monoio 性能测试实践thread per core 的 io_uring 运行时与 Tokio、Glommio 的吞吐、延迟和 CPU 开销对比 本文基语言运行时后端网络async-std 与 Tokio 对比分析选择适合你的异步运行时async std 与 Tokio 对比分析选择适合你的异步运行时 在 Rust 异步编程生态中async std 和 Tokio 是两个最流行的异步运行时异步编程并发编程Glommio与Tokio对比分析何时选择线程每核架构Glommio与Tokio对比分析何时选择线程每核架构 在现代异步Rust生态中 Glommio 和 Tokio 是两个备受瞩目的异步运行时。Glommi后端开发工具上一篇5分钟掌握Trippy网络诊断新利器完全指南下一篇Easy-Vibe SSH 密钥认证实战指南一条命令告别 GitHub 与服务器的密码登录创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考