< 返回版块

Yuan YQ 发表于 2025-03-25 09:55

探索更优的异步磁盘 I/O 方案

这篇文章围绕异步 Rust 磁盘 I/O 展开研究,作者所在团队因构建数据库 Tonbo 的需求,开发 Fusio 以优化磁盘 I/O 效率,并通过基准测试对比多种方案,得出不同场景下的性能结论。

研究背景

在构建基于异步 Rust 的分层存储数据库 Tonbo 时,磁盘 I/O 效率至关重要,但异步 Rust 的磁盘 I/O 存在不足,主要是由于全异步文件 I/O API 在主流操作系统中较新。为此开发 Fusio,它是一个低成本抽象层,能在不同平台提供统一异步数据访问,还可在不同异步运行时(如 Tokio、tokio-uring、monoio 和 WASM executor)间无缝切换。

测试设计

  • 测试场景:聚焦顺序写入和随机读取两种场景,因为多数平台和存储介质对其支持良好,且基于这两种操作可构建高效数据库,如 Tonbo 使用的 Parquet 文件结合 LSM-Tree 适用于这种读写模式。
  • 测试环境:在 AWS EC2 t3a.xlarge 实例上进行基准测试,运行 Linux Kernel 6.1.119 - 129.201.amzn2023.x86_64,Amazon Linux 2023 系统,cargo 1.85.1。
  • 对比方案:对比 fusio/monoio(使用 io_uring 作为 I/O API 的 async 运行时)、tokio(最流行的异步 Rust 运行时,磁盘 I/O 使用线程池)、fusio/tokio(利用 spawn_blocking 和 block_in_place 结合 write 和 pread 减少随机读取系统调用开销),在有计算负载场景中还引入 Apache Opendal(使用 spawn_blocking + pwrite/read 作为底层 I/O API)。

测试结果

  • 无负载场景:4KB 随机读取测试中,原生 Tokio 比最快的 fusio/tokio 慢 44 倍,原因是 I/O 线程与线程池工作线程同步开销和额外的 seek 系统调用,monoio 读写效率接近 write 和 pread;顺序写入测试中,fusio/monoio 和 fusio/tokio 表现优于原生 Tokio。
  • 有负载场景:Parquet 文件随机读取测试中,fusio/tokio 性能最佳;顺序写入测试中,fusio/tokio 表现较好,而 Opendal 的用户空间位置控制结合 pwrite 对顺序写入不理想。同时,monoio 在负载下随机读取性能不如无负载测试,原因是 Parquet 及其数据访问 API 内部默认运行时的工作窃取机制与基于 io_uring 的 Rust 异步运行时不兼容,产生额外同步开销,且 io_uring 的设计在高并发和 I/O 压力下更注重吞吐量,会牺牲一定延迟性能。
无负载场景对比:
	                 random read (4KB)
             ╔══════════════════════════════════════════════════╗
tokio        ╢██████████████████████████████████████████████████╟ 110.02
fusio/monoio ╢██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░╟ 3.7844
fusio/tokio  ╢█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░╟ 2.4747
             ╠══════════════════════════════════════════════════╣
             0                                                  110.02 / µs


		      sequential write (4KB)
             ╔══════════════════════════════════════════════════╗
tokio        ╢██████████████████████████████████████████████████╟ 66.49
fusio/tokio  ╢█████████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░╟ 28.243
fusio/monoio ╢███████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░╟ 25.609
             ╠══════════════════════════════════════════════════╣
             0                                                  66.49 / µs
				(lower is better)

原文:https://tonbo.io/blog/exploring-better-async-rust-disk-io

Fastrace:一个现代化的分布式追踪系统

在当今的微服务和分布式系统中,理解应用程序内部的运行情况极具挑战。传统的日志记录方法在面对用户请求涉及多个服务的场景时显得不足,分布式追踪能够创建请求跨服务边界的连接视图,帮助识别性能瓶颈、调试组件间复杂交互、理解依赖关系、分析延迟分布和异常值,以及将日志和指标与请求上下文关联起来。

tokio-rs/tracing是 Rust 开发者常用的应用程序检测解决方案,通过初始化追踪订阅者、创建跨度(span)记录数据,以及使用属性宏来检测函数。但是也面临一些挑战:一是生态系统碎片化,其自定义的日志宏与标准log crate 存在差异,导致库作者在选择使用时面临兼容性与可观测性的两难抉择,并且应用程序使用时还需额外配置 tracing-log 桥接器。二是对库的性能影响较大,库作者需要在始终检测带来的性能开销、不检测导致的可观测性缺失以及创建额外的功能标志系统增加维护负担之间做出选择。三是缺乏上下文传播,在分布式系统中,这会导致追踪不完整,难以跟踪请求流程、隔离性能问题和理解服务间的因果关系。

因此,有了 Fastrace,它具有以下特性:

  • 零成本抽象:当禁用时,其检测代码在编译时完全省略,不会产生运行时开销,适合对性能敏感的库。
  • 生态系统兼容性:专注于分布式追踪,通过可组合设计与现有 Rust 生态系统无缝集成,与标准log crate 兼容,库可以在不限制用户日志设置的情况下实现全面追踪。
  • 简单易用:API 设计直观,只需少量样板代码,在满足常见用例的同时具备扩展性。
  • 性能卓越:专为高性能应用设计,能处理大量跨度,对 CPU 和内存使用影响小。
  • 对应用和库都友好:库使用fastrace时,在应用未启用相关功能时无性能损失;启用后,库中的检测代码生效,应用可全面了解库的行为。
  • 无缝上下文传播:为流行框架提供配套的 crate,自动处理上下文传播,如在 HTTP、gRPC、数据访问等场景中无需手动处理上下文即可实现开箱即用的分布式追踪。

Github 仓库:https://github.com/fast/fastrace

LibrePCB 1.3.0 发布,首次引入 Rust 代码

LibrePCB 是一款免费的、跨平台且易于使用的电子设计自动化套件,可用于绘制原理图以及设计印刷电路板。无论是创客、学生还是专业人士,从初学者到专家,都能使用它。在完全使用 C++ 开发 LibrePCB 超过 10 年后,1.3.0 版本包含了用 Rust 编程语言编写的首批代码。

这背后的原因在博客文章《LibrePCB 2.0 的 NGI0 资助》(https://librepcb.org/blog/2024-10-17_roadmap_2.0/)中有解释。虽然这在 LibrePCB 应用程序中并不直接可见,但用户仍能从潜在的更高稳定性和更快开发速度中间接受益。

在这个版本中,有两个用 Rust 实现的软件模块:交互式 HTML 生成器,以及用于读写 ZIP 文件的库。

官网:https://librepcb.org/

--

From 日报小组 Yuan YQ

社区学习交流平台订阅:

评论区

写评论

还没有评论

1 共 0 条评论, 1 页