如果你维护过一套大型系统,大概能体会这种痛苦:遗留代码用着旧技术栈,跑得慢、占内存,但没人敢动它——因为一改就可能牵一发动全身。GitHub 最近干了一件疯狂的事:把 Copilot CLI、Copilot 应用和 Copilot SDK 背后的运行时,从 TypeScript 和 Node.js 整体迁移到 Rust,替换了超过 80 万行生产代码,整个过程只用时约 14.5 周,而且是在不停发版的情况下完成的。
迁移之后的效果是实打实的:客户端启动、会话创建、单轮对话这一整套流程,从旧运行时的 5.25 秒锐减到 292 毫秒,快了接近 18 倍。为什么会有这么大差距?关键在运行时的集成方式。旧实现依赖 Node.js 和 V8 引擎,宿主应用要跟它通信得跨进程,每次得额外加载约 100 MB 的工作集内存。Rust 版本通过 C ABI(C 应用程序二进制接口,一种跨语言调用的标准约定,让 Rust 代码能直接被其他语言链接)直接嵌进宿主进程,省掉了进程边界和大部分内存开销。当然,如果你不想内嵌,也保留了独立进程模式。现在 Copilot SDK 支持 TypeScript、Python、Go、.NET、Java 和 Rust,覆盖了主流语言。

最值得学习的是它的迁移策略——不是“重写一遍再一次性切换”,而是“增量替换 + 临时兼容层”。GitHub 把一个个 TypeScript 组件换成 Rust 实现,中间用 N API(Node.js 的原生插件接口,允许 C/C++ 代码与 JavaScript 互相调用)暂时搭建互操作桥梁。这样旧代码还能跑,新代码也能被端到端测试覆盖。整个迁移期间,他们发布了 135 个版本,其中 35 个是稳定版、100 个是预发布版,始终保持对外可用。这种“小步快跑”而不是“一锤子买卖”的做法,大大降低了风险。

为了支撑这种混合状态,他们编写的兼容层一度达到了 2,019 个 N API 导出和 3,356 个 TypeScript 调用点,最后才拆除。到 8 月 21 日,运行时里已经有 832,378 行生产 Rust 代码,还有 468,689 行 Rust 单元测试。AI 生成了绝大部分实现代码,但人类的编译、测试和代码审查是关键——因为光靠编译通过远不够,还要检查行为、状态和生命周期处理、库语义差异以及丢失的优化。GitHub 记录了 4,478 次 cargo check(Rust 的编译检查命令)运行,其中 87.1% 一次性通过,剩下的就是需要人工盯的坑。

社区对这个案例的讨论,焦点不全在“AI 写了 Rust 代码”这件事上,而是这种 AI 辅助迁移如何保证行为边界稳定。有用户指出,取消操作、重试逻辑、背压(下游处理不过来时向上游反馈减速的机制)这些场景,光靠编译和单测很难验证完整。另一位工程师则强调,小步可审查变更、兼容层、以及人类的工程判断,是这套方法能成功的关键要素。


还有一个容易忽略的难点:遗留系统里往往藏着没写进文档的行为约定。比如某个接口在特定输入下返回的错误码、某些超时阈值,这些在旧代码里靠隐式逻辑存在,迁移时很容易被 AI 生成的“看起来正确”的代码悄悄改掉。GitHub 的做法是让自动化测试和人工 review 一遍遍去撞这些边界。

这件事给我们的启发是什么?如果你需要把旧系统换掉底层技术栈,别急着“推倒重写”。先想想能不能像 GitHub 这样:用兼容层维持运行,增量替换,让 AI 生成初稿,但把验证重点放在行为等价上而不是编译通过上。这个过程里,测试用例的价值会被放大——你现有的测试越多,迁移就越安全。另外,AI 辅助迁移不是“一键完成”,它更像是“AI 写,人审”,边界行为、生命周期、异常处理这些地方,AI 最容易犯迷糊,必须人工兜底。如果你手头有大量遗留代码,想换更快的语言或者更省内存的运行时,这 14.5 周的真实战例,很值得照着走一遍。
内容与图片版权归原作者所有 · 原文: https://www.infoq.com/news/2026/10/github-copilot-rust-migration/?utm_campaign=infoq_content&utm_source=infoq&utm_medium=feed&utm_term=global