迈向 10 倍性能飞跃:TypeScript 编译器原生移植(Corsa)的技术解析
摘要
TypeScript 项目的负责人宣布启动一项代号为 Corsa 的重要工作,旨在将现有的 JavaScript/TypeScript 编译器和工具集原生移植到 Go 语言。此举是为了彻底解决在大型代码库中 TypeScript 长期存在的性能瓶颈,包括加载时间长、检查耗时以及内存溢出等问题。通过这项移植而非重写的工作,项目旨在实现 10 倍的构建速度提升和 8 倍的编辑器项目加载速度提升。该原生版本预计将作为 TypeScript 7.0 发布。
一、 性能驱动的变革
TypeScript 的核心价值在于提供卓越的开发者体验,然而对于拥有数百万行代码的超大型项目,现有 TypeScript(代号 Strada)的性能扩展能力已达极限。现有的 JavaScript 运行时(JIT 编译、灵活的对象模型、缺乏共享内存并发)限制了编译器作为计算密集型系统工具的潜力。
通过将代码库移植到原生 Go 语言,团队预计将实现以下关键性能指标:
- 构建速度提升: 大部分构建时间将减少 10 倍。例如,对 Visual Studio Code 项目(约 150 万行代码)进行
tsc编译的时间,从 77.8 秒缩短至 7.5 秒,加速比达到 10.4 倍。 - 编辑器加载速度提升: 编辑器的启动时间将显著改进。在编辑器场景中,VS Code 项目的加载时间从大约 9.6 秒降至约 1.2 秒,实现了 8 倍的改进。
- 内存效率: 总内存使用量预计约为现有实现的一半。
这种性能的大幅提升(10 倍)将为更高级的重构、更深层次的代码洞察以及下一代 AI 增强开发工具提供基础支持。
二、 技术选择与实现方法
1. 选择 Go 语言
开发团队在评估了多种语言(如 C、Rust、C++)后,选择了 Go 语言作为移植目标。Go 被认为是最适合编译器和系统级工具工作负载的语言,因为它提供了以下优势:
- 完全优化的原生代码支持:在所有平台上均可获得。
- 对数据布局的良好控制:允许创建循环数据结构。
- 自动内存管理:提供了垃圾回收机制。
- 出色的并发支持:能够充分利用多核优势。
2. “移植而非重写”的策略
该项目采用“移植而非重写”的策略,意味着开发人员是逐文件、逐函数地将代码从 TypeScript 迁移到 Go。这一核心决策是为了保留所有隐式行为和语义,确保新编译器在类型检查、错误报告等方面的行为与现有编译器完全一致。这意味着对于相同的输入,无论使用旧编译器还是新编译器,报告的错误、位置和消息都将相同。
3. 利用并发性实现加速
性能的巨大提升(10 倍)中,大约一半来自原生代码,另一半来自并发性的使用。
- 并行化解析和绑定: 编译器在解析、绑定和代码生成阶段实现了完全并发。这些过程被认为是“令人尴尬地并行化”的问题,因为它们大多是文件本地的操作,可以充分利用多核处理器。
- 并发式类型检查: 类型检查更具挑战性,因为它涉及跨文件的依赖关系。解决方案是创建多个类型检查器(当前硬编码为四个),每个检查器负责检查程序中约四分之一的文件。尽管这会在标准库等地方造成少量重复工作和内存消耗(多消耗约 20-25% 的内存),但整体上仍能实现 2 到 3 倍的检查阶段加速,并保持整体内存消耗低于现有实现。
三、 功能模块对等性(与 TS 5.9 对比)
Go 原生移植版(Corsa)旨在作为现有 TypeScript 的即插即用替代品。根据项目状态,核心功能已达到与 TypeScript 5.9 的高度对等:
| 功能模块 | 状态 (定义:已完成 / 进行中 / 原型 / 尚未就绪) | 细节说明 |
|---|---|---|
| 解析/扫描 | 已完成 | 与 TS 5.9 具有完全相同的语法错误。 |
程序创建 / tsconfig.json 解析 | 已完成 | 文件和模块解析与 TS 5.9 相同;tsconfig 错误提示可能不如现有版本有用。 |
| 类型解析与检查 | 已完成 | 与 TS 5.9 具有相同的类型;错误、位置和消息相同。 |
| JSX 支持 | 已完成 | |
| 构建模式 / 项目引用 | 已完成 | |
| 增量构建 (Incremental build) | 已完成 | |
| 代码生成 (Emit / JS output) | 进行中 | target: esnext 支持良好,其他目标可能存在差距。 |
| JSDoc & JS 特定推断 | 进行中 | 大部分已完成,但声明文件生成尚未完成。 |
| 声明文件生成 (Declaration emit) | 进行中 | 大多数常见功能已就位,但一些边缘情况和功能标志尚未处理。 |
| 语言服务 (Language service) | 进行中 | 大部分功能已实现,正在转向使用 LSP 架构(Language Server Protocol)。 |
| Watch 模式 | 原型 | 可监视文件和重建,但没有增量重新检查,且尚未优化。 |
| API | 尚未就绪 |
展望: 团队计划在今年内(源材料发布年份的年内)交付一个功能齐全的命令行编译器替代品,支持 JSDoc、JSX 和项目引用。一旦 Go 代码库达到足够的对等性,它将作为 TypeScript 7.0 正式发布。