从 C 迁移到 Rust:AV1 解码器移植的挑战与经验教训
InfoQ 2024年10月24日
互联网安全研究小组 (ISRG) 的软件工程师 Stephen Crane 和 Khyber Sen 近期在 InfoQ 上发表了一系列文章,详细讲述了他们如何将 VideoLAN 和 FFmpeg AV1 解码器从 C 语言移植到 Rust 语言。该项目旨在为 AV1 解码器 dav1d 提供一个安全、高性能的 Rust 实现,并克服 C 语言带来的内存安全问题。
dav1d 是 VideoLan VLC 和 FFMpeg 中使用的 AV1 解码器,已经开发了六年多,包含大约 5 万行 C 代码和 25 万行汇编程序。由于代码高度优化,dav1d 具有体积小、可移植性好、速度快的特点。因此,ISRG 团队决定进行移植,而不是从头开始用 Rust 重写。
移植挑战:C 和 Rust 之间的鸿沟
将 dav1d 移植到 Rust 面临着诸多挑战,主要源于 C 和 Rust 之间的语言差异,以及 dav1d 代码本身的设计特点。
- 内存管理: Rust 的内存管理机制与 C 语言截然不同,Rust 采用所有权和借用机制来确保内存安全,而 C 语言则依赖于手动内存管理。这导致了在移植过程中需要对内存管理进行彻底的重构。
- 线程安全: dav1d 代码中存在大量的跨线程共享可变数据访问,这在 Rust 中是一个潜在的安全隐患。ISRG 团队使用 Mutex 和 RwLock 加锁机制来确保线程安全,并通过验证机制来避免引入延迟。
- 自引用结构: dav1d 代码中使用了一些自引用结构,而 Rust 不允许使用自引用结构。ISRG 团队通过使用整数索引和函数参数引用来解决这个问题。
- 无标签联合体: dav1d 代码中使用了无标签联合体,而 Rust 要求联合体必须带标签。ISRG 团队使用 zerocopy crate 来解决这个问题。
性能优化:保持速度,确保安全
移植过程中,ISRG 团队始终将性能作为首要目标。他们通过监控性能回归情况,并对动态分派汇编代码、边界检查、结构初始化等方面进行优化,最终将移植带来的性能开销降低到6%。
经验教训:从 C 到 Rust 的跨越
整个移植过程耗费了三个开发人员 20 多个月的时间,比最初预计的时间要长。但最终的结果表明,将现有的 C 代码重写为安全、高性能的 Rust 代码是可行的。
ISRG 团队从 dav1d 的移植过程中总结了以下经验教训:
- 全面测试至关重要: 从一开始就进行全面的 CI 测试,可以确保代码库的稳定性和安全性。
- 专业知识的协同: 即使团队成员在 Rust 和系统编程方面经验丰富,也需要专业领域的专家提供指导。
- 性能优化不可忽视: 在确保安全性的同时,也要关注性能优化,以避免移植带来的性能损失。
未来展望:Rust 在安全领域的应用
dav1d 的移植项目证明了 Rust 在安全领域应用的潜力。Rust 的内存安全特性和丰富的工具库可以帮助开发人员构建安全、可靠的软件系统。
随着 Rust 语言的不断发展,以及开发者社区的不断壮大,相信 Rust 将在更多领域发挥重要作用,为软件开发带来新的安全和性能保障。
Views: 0