2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

从 C 迁移到 Rust 的挑战与经验教训

作者:Sergio De Simone

  • 2024-11-18
    北京
  • 本文字数:1595 字

    阅读完需:约 5 分钟

从 C 迁移到 Rust 的挑战与经验教训

在一个系列文章中,Immunant 软件工程师 Stephen Crane 和 Khyber Sen 讲述了他们如何将互联网安全研究小组 (ISRG) 的 VideoLAN 和 FFmpeg AV1 解码器从 C 语言移植到 Rust 语言。该系列文章详细介绍了他们如何确保不出错并优化性能。


VideoLan VLC 和 FFMpeg 中使用的 AV1 解码器 dav1d 已经开发了六年多,包含大约 5 万行 C 代码和 25 万行汇编程序。正如 Crane 所说的那样,它成熟、速度快且应用广泛。因为代码高度优化,所以它的体积小、可移植性好、速度快。因此,他们坚持要移植,而不是使用 Rust 从头开始重写。


Immunant 的工程师们首先要做的选择是,是一步一步地进行移植,还是使用 c2rust 移植整个代码库,获得一个不安全但可运行的 Rust 实现,然后再以此为基础进行重构和重写,使其变得安全而又符合 Rust 的语言习惯。最终,他们决定采用 c2rust,因为它有两大优势:一是可以在重构的同时测试移植的代码,二是降低了对专家领域知识的要求。


我们发现,在重写和改进 Rust 代码的过程中,从一开始就进行全面的 CI 测试是非常有益的。我们可以对代码库进行横向修改,并在每次提交时运行已有的 dav1d 测试。[…] 该项目的大部分团队成员都是系统编程和 Rust 方面的专家,但之前并没有 AV 编解码器方面的经验。我们的编解码器专家 Frank Bossen 为项目提供了宝贵的指导,但大部分的工作他并不需直接要参。


将移植生成的 Rust 代码重构为安全、符合语言习惯的 Rust 代码面临着许多挑战,其中一些挑战与 C 和 Rust 之间的不匹配有关,例如生命周期管理(借用)、内存所有权、缓冲指针和联合体;另一些挑战则源于 dav1d 的设计,它非常依赖于对跨线程共享可变数据的访问。


通过使用MutexRwLock加锁,并在运行时使用Mutex::try_lock()RwLock::try_read()/RwLock:: try_write()进行验证,他们确保了线程可以访问数据而且又不会引入延迟,从而解决了与共享状态相关的线程安全问题。


这种方法可以很好地处理只有一个线程需要修改跨线程共享值的情况。然而,dav1d 还依赖于多个线程对单个缓冲区的并发访问,其中每个线程访问缓冲区的特定子区域。对此,Immunant 工程师并没有使用更符合 Rust 语言习惯的方法,即使用专门分配给不同线程的不相连的区域,而是创建了一个缓冲区封装类型DisjointMut,负责处理可变借用,并确保每一个都能独占访问。


另外两个颇具挑战性的领域是自引用结构(主要用于跟踪缓冲区位置的游标以及上下文结构之间的链接)和无标签联合体。由于 Rust 不允许使用自引用结构,所以游标指针被整数索引取代,而上下文结构之间的链接被取消,并通过函数参数进行引用。在适当的时候,无标签联合体会被转换为带标签的 Rust 联合体,而在其他情况下,zerocopy crate 会在运行时将相同的字节重新解释为两种不同的类型,以避免改变联合体的表示和大小。


移植的一个主要目标是保持性能不变。因此,Immunant 的工程师在每次提交的重构阶段都会仔细监控性能回归情况。在向安全代码转换的过程中,他们意识到,性能主要是受到一些微妙因素的影响,如动态分派汇编代码、边界检查和结构初始化的成本。最后,他们进行了与分支、内联和堆栈使用相关的更细致的优化。


性能优化工作显著降低了移植带来的开销,从 11% 降至 6%。按照 Crane 的说法,总体上,将 dav1d 移植到 rav1d 花费了三个开发人员 20 多个月的时间,所耗费的人工比最初预计的要多。但这也表明,将现有的 C 代码重写为安全、高性能的 Rust 代码并解决所有线程和借用难题是可能的。


对特别注重安全性的应用程序,rav1d 提供了一个内存安全的实现,而且不会因为沙箱等风险缓解措施而额外增加开支。我们相信,通过不断地优化和改进,在任何情况下,Rust 实现都可以与 C 语言实现相媲美,同时还能提供内存安全性。


他们从 rav1d 的诞生过程中学到的东西远不止这些,如果想了解更多信息,请阅读原文。


查看原文链接:

https://www.infoq.com/news/2024/10/porting-av1-decoder-rust/

2024-11-18 08:107062

评论

发布
暂无评论
发现更多内容

SD-WAN: 灵活部署,助力云服务

Ogcloud

SD-WAN 企业网络 SD-WAN组网 SD-WAN服务商 SDWAN

软件测试学习笔记丨WebSocket原理&使用

测试人

软件测试 测试开发

广州孚瑞经营改善 企业经营持续增长方案提供商

广东孚瑞经营改善

精益生产

IT外包对企业业务流程整合有什么帮助?

Ogcloud

IT IT外包 IT外包公司 IT外包服务

Dapp质押挖矿丨云算力挖矿系统开发

l8l259l3365

软件测试学习笔记丨性能监控系统部署

测试人

软件测试 自动化测试 测试开发

NineData云原生智能数据管理平台新功能发布|2024年2月版

NineData

MySQL 数据复制 tdsql NineData GaiaDB

淘宝天猫详情接口API:快速实现商品信息查询和展示

联讯数据

IT外包提升企业灵活性与敏捷性

Ogcloud

IT IT外包 IT外包公司 IT外包服务

人工智能在现代科技中的应用和未来发展趋势

贺公子之数据科学与艺术

探索机器学习视觉处理的未来前景

测吧(北京)科技有限公司

测试

安全SCDN有什么效果

德迅云安全杨德俊

AI Agent涌向移动终端,手机智能体开启跨端跨应用业务连接新场景

王吉伟频道

生成式AI AI智能体 AIAgent 手机Agent 手机智能体

如何简化 Kubernetes 出入向流量管理

NGINX开源社区

Kubernetes 微服务 Ingress Controller 流量管理

「外部参数」功能已上线,爷们儿速来体验!!

Jianmu

UIDiff检测技术解密:为何对UI自动化测试至关重要?

测吧(北京)科技有限公司

测试

深度学习驱动的遍历动作推荐:提高UI自动化测试效率的创新方法

测吧(北京)科技有限公司

测试

视觉场景案例中的响应时间分析与弹窗检测

测吧(北京)科技有限公司

测试

如何做代币分析:以 USDC 币为例

Footprint Analytics

blockchain Token

Sermant运行流程学习笔记,速来抄作业

华为云开发者联盟

开发 华为云 华为云开发者联盟 sermant

前端的你常用的编程语言有哪些?

小齐写代码

应用监控 eBPF 版:实现 Golang 微服务的无侵入应用监控

阿里巴巴云原生

阿里云 云原生 应用监控

云消息队列 Confluent 版正式上线!

阿里巴巴云原生

阿里云 云原生 Confluent

解析UI页面结构树的逆向解析服务化:技术探索与应用

测吧(北京)科技有限公司

测试

新潮视觉识别技术:基于无监督深度特征的视角分析

测吧(北京)科技有限公司

测试

无参照模型预测技术:UI自动化测试的新思路与应用

测吧(北京)科技有限公司

测试

从 C 迁移到 Rust 的挑战与经验教训_编程语言_InfoQ精选文章