I made a build visualizer to understand Bun's compile times
171 points • 2 days agoArticle Link

buildprof 的作者开发了这个开源追踪工具,用来调查 Bun JavaScript runtime 中一次从基于 Zig 的构建迁移到基于 Rust 的构建后据称带来五倍编译速度提升的差异。工具通过记录构建过程中启动的每一个进程和子进程并把它们映射到时间轴上,能够以细粒度呈现复杂软件项目的编译过程。 buildprof 与具体构建系统无关,它捕获完整的进程树,能清楚暴露出并行性不足或单一的大规模链接步骤等低效环节。

在单机重现构建时间后,作者发现老的 Zig 构建在最后阶段被一次巨大的链接调用严重拖慢,该阶段约占整体构建时间的三分之二,并启用了 Full Link-Time Optimization (LTO) 。相比之下,新的 Rust 构建使用了 ThinLTO,从而更好地实现了并行化。调查还显示,Bun 的 Zig 构建几乎把所有代码汇聚到一个巨大的模块中,而 Rust 构建则把工作分散到了 90 多个独立的 crates 中。

进一步研究表明,单靠改编译器选项并不能解决问题。因为 Bun 下载的预编译 WebKit 库已经内置了 Full-LTO,链接器仍然要承担大量优化任务。作者在启用 ThinLTO 的情况下手动重建这些 WebKit 依赖并更新构建配置后,成功将链接时间从 16 分钟缩短到 7 分钟,但仍比 Rust 构建慢。最终剩余的时间差被归因于两种构建在代码库结构和管理方式上的根本性差异。

在实现上,buildprof 利用 Linux 的 ptrace 接口来监控进程的 fork 、 exec 和 exit,因为针对这个用例它比 eBPF 或 ftrace 更直接、侵入性更小。工具还用 seccomp 过滤器追踪文件系统交互,给构建过程只带来极小的开销。其可视化界面基于 Perfetto 追踪框架,用户不仅可以看到任务的耗时,还能观察文件生产者和消费者之间的依赖关系。

该项目强调,现代构建过程往往复杂且混乱,可能包含意外的诊断探测、网络拉取和隐藏的依赖链。通过将这些隐蔽活动可视化,作者希望为开发者提供一种实用手段来识别并修复性能瓶颈。 buildprof 的后续迭代计划包括提升文件系统追踪的效率、扩展对 macOS 和 Windows 的支持,并有可能实现自动化的关键路径分析,以进一步简化优化工作。

31 comments • Comments Link

WebKit 中的 Full Link Time Optimization (LTO) 实际上是串行执行的,专用可视化工具可以帮助开发者区分链接阶段与代码生成阶段。

试图把 Bun 的 Zig 模块拆成更小的部分以缩短编译时间很困难,因为 Zig 缺乏像 Rust 那样基于 crate 的原生模块化机制;拆分后往往不得不放弃泛型(generics)、切片(slices)等语言特性。

Zig 的独立编译单元带来的性能问题通常可以通过 LTO 缓解,尽管编译器本身无法自动将大型单元并行化为可独立优化的部分。

对 Zig 的语义分析 (semantic analysis) 进行并行化被认为能缩短构建时间,但现有实现往往难以保证生产级构建所需的确定性。

在比较 Zig 与 Rust 的构建性能时需要考虑 crate 的并行性;Rust 能独立编译 crate,但这并不能完全解释复杂构建中出现的性能差异。

Zig 在调试和增量构建方面仍然很有竞争力,通常能提供比当前 Rust 环境更快、更流畅的开发体验。

先进的构建分析工具使开发者能够做根本原因分析,定位导致构建瓶颈的具体任务,而不必依赖直觉判断。

自动化分析与 AI 驱动的优化是构建系统的潜在发展方向,但以人为主导的可视化工具在诊断复杂且不易察觉的性能退化问题上仍更为有效。

此次讨论凸显了对构建性能的高度关注以及利用先进分析工具揭示复杂编译过程细节的实用价值。 Zig 的单体编译单元所允许的语言特性与 Rust 的 crate 结构所带来的并行优势之间存在明显权衡,但与会者指出这些差异往往很微妙且高度依赖具体应用场景。大家对更易用的诊断工具表示欢迎,同时也认识到,自动化方案目前尚不能取代深厚的人类专业知识来排查错综复杂的系统级性能问题。