文章摘要
作者使用Rust新引入的become关键字实现了一个尾调用解释器,性能优于之前的Rust实现和手写ARM64汇编代码。这是作者对Uxn CPU高性能模拟探索的最新成果,延续了他之前关于Raven项目和ARM64优化的研究。
文章总结
标题:在(Nightly)Rust中实现尾调用解释器
作者:Matt Keeter 发布时间:2026年4月5日
主要内容:
- 项目背景
- 作者使用Rust新引入的
become关键字(7个月前添加到nightly版本)实现了尾调用解释器 - 该解释器性能优于作者之前用Rust和ARM64汇编实现的版本
- 项目属于对Uxn CPU高性能模拟的探索系列
- Uxn模拟基础
- Uxn是简单的栈式机器,具有256条指令
- 包含两个256字节的栈、64KB RAM、2字节程序计数器和256字节设备内存
- 基本模拟器通过读取程序计数器处的字节并调用相应指令来运行
- 汇编实现
- 使用"token threading"技术,将CPU状态存储在寄存器中
- 每条指令末尾跳转到下一条指令,提高分支预测效率
- ARM64性能提升40-50%,x86-64提升约2倍
- 但需要维护约2000行不安全代码
- Rust尾调用实现
- 利用函数参数存储程序状态(映射到寄存器)
- 每条函数末尾调用下一条函数
- 使用
become关键字确保尾调用优化 - 完全安全的Rust代码(无unsafe)
- 性能对比
- ARM64(M1 Macbook):
- 尾调用实现优于手写汇编
- Fibonacci测试:1.19ms vs 1.32ms(汇编)
- Mandelbrot测试:76ms vs 87ms(汇编)
- x86-64:
- 尾调用实现仍落后于手写汇编
- Fibonacci测试:3.23ms vs 1.84ms(汇编)
- 代码生成存在优化空间(寄存器使用等)
- WebAssembly支持
- WASM也支持尾调用,但性能表现不佳
- 在Firefox、Chrome和wasmtime中都比传统VM实现慢
- 项目状态
- 尾调用解释器已合并并发布在0.3.0版本
- 在ARM64系统上默认启用
- 作者欢迎关于改进x86和WASM性能的建议
技术亮点: - 使用Rust宏减少样板代码 - 完全安全的实现(无unsafe代码) - 展示了Rust nightly特性的实际应用 - 提供了详细的代码生成分析和性能对比
评论总结
以下是评论内容的总结:
高效虚拟机/解释器的优势
- 观点:高度专业化的虚拟机/指令解释器在性能和代码紧凑性上表现优异
- 论据:
- "resulting VM outperforms both my previous Rust implementation and my hand-coded ARM64 assembly"(虚拟机性能优于手写ARM64汇编)
- "specialized mini VMs are... an extra flexible form of dynamic dispatch"(迷你虚拟机是动态分发的灵活形式)
尾递归调用的价值
- 观点:尾递归优化为循环宏提供了可能性
- 论据:
- "Tail recursion opens up for people to write really really neat looping facilities using macros"(尾递归支持通过宏实现优雅循环)
- 需区分普通尾调用与尾调用优化:"Tail calls alone aren't special... what matters is reusing caller's frame"(关键在于复用调用帧而非单纯尾调用)
语言偏好
- 观点:单纯因使用Rust语言而认可
- 论据:
- "i like it because it's in rust"(明确表达对Rust的偏好)
技术准确性补充
- 观点:需明确区分尾调用与尾调用优化
- 论据:
- "More accurate title would be to say it is a tail call optimized interpreter"(应强调"优化"特性)
总结呈现了效率优势(3条论据)、语言特性(2条论据)、语言偏好(1条论据)三个维度,其中技术性讨论占比80%。争议点在于尾调用优化的实际价值,但未出现对立观点。