Relax 通过仅在函数首次被调用时进行编译,消除了 Rust 开发中传统的“构建后运行”循环。作为 Makepad 项目的一部分开发的这一 JIT(即时编译)运行时允许开发者将编辑内容直接补丁到运行中的进程中,在保持程序状态的同时无需完全重启。

按需编译与热补丁

与标准 Cargo 和 rustc 工作流不同(其中程序必须在执行前完全编译),Relax 直接从源代码运行 Cargo 包。它在每次函数被调用时编译该函数,并在程序运行时在后台优化“热点”函数。

这种方法的一个关键特性是热补丁。当开发者保存文件时,Relax 会重新检查并重新编译更改的函数,并将它们交换到运行中的进程中。这允许立即迭代,同时保留应用程序的状态——例如 3D 游戏的当前帧或 UI 的当前布局——在代码更改过程中保持不变。

粒子在实时函数补丁期间改变运动的视觉演示。
热补丁演示,其中粒子在不重启应用程序的情况下立即更新其运动行为。makepad.github.io

这张图片展示了热补丁的概念,即应用程序状态(如 3D 游戏的粒子运动)在代码更改过程中得以保留。

“Relax 在构建你的程序的同时运行它。”

— Relax: Rust without the wait

JIT 特定开发者工具

由于 Relax 作为 JIT 运行时运行,它提供了专门的调试和分析功能。它包括“在恐慌时暂停”功能,该功能会保留堆栈完整地挂起线程,允许开发者直接在恐慌帧中读取局部变量并评估 Rust 表达式。

该系统还提供“飞行记录仪”,用于保存最后几分钟的线程事件,以及“why-hung”命令用于诊断死锁或阻塞的线程。对于性能分析,它提供“why-slow”工具,通过对 JIT 和原生帧进行采样来识别热点行和调用树。

性能权衡与限制

与原生 CPU 构建相比,使用 Relax 有可衡量的性能成本。在稳态下,Relax 生成的代码比 rustc 的 --release 输出慢,在 21 个工作负载中,相对于原生构建的几何平均减速为 1.22x 到 1.25x。

显示 Relax 与 rustc 之间性能指标的对比表。
性能对比表,突出了 Relax 的 JIT 执行与标准 rustc 构建之间的权衡。makepad.github.io

该表提供了关于使用 Relax JIT 运行时与原生构建相比的性能开销的具体数据点。

该系统还会消耗更多内存,因为编译器、其缓存以及每个发布的代码版本都与程序的进程共享。此外,虽然函数体可以进行热补丁,但结构性更改(如修改后的结构体布局、导入或 trait 头部)仍需要重新启动会话。

Hacker News 读者的反应

  • 替代方案: 一位分享了与其他工具经验的评论者指出,他们一直在使用 "mr boxington" 来帮助他们的工作流。 评论 ↗
  • 质疑: 一位评论者对项目的范围表示怀疑,认为完全重新实现 Rust 是一个极其宏大的任务。 评论 ↗
  • 质疑: 另一位用户质疑项目的前提,认为 Rust 的构建时间在过去十年中并不是一个重大问题,并且它与 Lisp 有本质区别。 评论 ↗
  • 质疑: 一位评论者建议,该项目是 AI 智能体能够实现目标的典型例子,即通过处理那些雄心勃勃但概念上已被充分探索的任务,而这些任务以前需要投入过多的手动精力。 评论 ↗

以上为 Hacker News 讨论中观点的摘要,并非经过核实的事实。 阅读完整讨论 ↗