Wren 编程语言的性能表现
摘要
Wren 官网发布微基准测试,称其运行速度超过标准 Python/Ruby/Lua 解释器,同时仍保持简单的字节码虚拟机,得益于 NaN 标记和固定对象布局。
<p><a href="https://lobste.rs/s/fgwvua/performance_wren_programming_language">评论</a></p>
查看缓存全文
缓存时间: 2026/04/21 14:27
# 性能 – Wren
来源:https://wren.io/performance.html
## 性能
虽然大多数跑分一文不值,但大家爱看,那就来几组:
### 方法调用
wren0.12s
luajit -joff0.16s
ruby0.20s
lua0.35s
python30.78s
python0.85s
### DeltaBlue
wren0.13s
python30.48s
python0.57s
### Binary Trees
luajit -joff0.11s
wren0.22s
ruby0.24s
python0.37s
python30.38s
lua0.52s
### 递归斐波那契
luajit -joff0.10s
wren0.20s
ruby0.22s
lua0.28s
python0.51s
python30.57s
**柱越短越好。**
每项跑 10 次取最佳成绩,仅统计基准代码执行时间,不含解释器启动。
测试机:MacBook Pro 2.3 GHz Intel Core i7,16 GB 1,600 MHz DDR3。
对比版本:Lua 5.2.3、LuaJIT 2.0.2、Python 2.7.5、Python 3.3.4、ruby 2.0.0p247。
LuaJIT 关闭 JIT(字节码解释模式),因为目标平台可能禁止 JIT。
若开启 JIT,LuaJIT 会比表中所有语言(包括 Wren)快得多——Mike Pall 是来自未来的机器人。
基准脚本与用例在[这里](https://github.com/wren-lang/wren/tree/main/test/benchmark)。
## Wren 为什么快?[#](https://wren.io/performance.html#why-is-wren-fast)
语言大致分四档性能:
1. 树遍历解释器:Ruby 1.8.7 及更早、Io、你大学作业写的解释器。
2. 字节码解释器:CPython、Ruby 1.9+、Lua、早期 JS 引擎。
3. JIT 动态语言:现代 JS 引擎、LuaJIT、PyPy、部分 Lisp/Scheme。
4. 静态类型语言:C、C++、Java、C#、Haskell 等。
第一档基本无法上生产(服务器可堆硬件例外)。
第二档对大多数客户端场景已足够快。
第三档非常快,但实现复杂度堪比静态语言编译器。
Wren 就在第二档——简单实现、速度够用。
此外,它还有几手绝活:
### 紧凑的值表示[#](https://wren.io/performance.html#a-compact-value-representation)
动态语言的核心是“万能变量”结构:要能存任意类型,又尽量小。
Wren 采用[NaN 装箱(NaN-tagging)](http://wingolog.org/archives/2011/05/18/value-representation-in-javascript-implementations):
所有值内部用 8 字节双精度浮点表示。
数值本身已是 double,算术无需转换,最快。
NaN 的位模式有大量空位,可塞进堆对象指针,还能留余量给 `true`、`false`、`null`。
于是数字、布尔、null 无箱,完整值仅 8 字节,64 位机器原生字长,更小=更快。
### 固定对象布局[#](https://wren.io/performance.html#fixed-object-layout)
多数动态语言把对象当“属性袋”,运行时可随意增删成员。
Lua、JavaScript 甚至没有固定“类型”概念。
Wren 严格基于类:
- 类声明后不可命令式修改;
- 字段对类私有,仅类内方法可访问。
于是**编译期**就能知道对象有几格字段,一次性分配正好大小的内存。
别的语言每次访问字段都要哈希查找,甚至沿继承链回溯;
Wren 的字段访问只是“编译期已知偏移”的指针加法。
### 复制式继承[#](https://wren.io/performance.html#copy-down-inheritance)
调方法时要找实现,可能沿继承链一路向上。
若运行时可动态增删方法或改继承树,就得每次都检查,浪费 CPU。
Wren 的继承关系在类定义完成时就固定,于是**创建子类时把继承的方法全部复制一份**。
之后的方法派发只需在接收者的类里找,无需爬链。
### 方法签名[#](https://wren.io/performance.html#method-signatures)
Wren 用[签名](https://wren.io/method-calls.html#signature)支持按参数个数重载,既增强表达力又提速:
找到方法的同时就确认了参数个数正确,
无需像多数语言那样运行时再检查参数过多或过少——语法上就传不错。
### 计算型 goto[#](https://wren.io/performance.html#computed-gotos)
在支持的编译器上,Wren 的字节码解释主循环使用[计算型 goto](http://eli.thegreenplace.net/2012/07/12/computed-goto-for-efficient-dispatch-tables/)。
解释器热点是围绕指令的巨大 `switch`,
普通 `switch` 会让 CPU 分支预测器崩溃——单一点饱和后预测失败、流水线冲刷。
计算型 goto 给每条指令末尾独立分支,各自预测,常见指令序列命中率高,实测快 5–10%。
### 单趟编译器[#](https://wren.io/performance.html#a-single-pass-compiler)
编译耗时在总性能里占比小,但影响**启动速度**。
Wren 的编译器仿 Lua:边解析边直接 emit 字节码,
不先生成完整 AST,内存分配极少,解析开销极低。
## 别的语言怎么不学?[#](https://wren.io/performance.html#why-don't-other-languages-do-this)
Wren 的快主要来自语言设计:
动态“类型”与“派发”仍在,但类的**定义**是静态的,省了很多事。
其他语言对象模型更 mutable,改不动,否则海量旧代码会炸。
Wren 最近的亲戚是 Lua。
Lua 比 Wren 更动态,因而更难优化;
同时 Lua 极度追求可移植:只要有 C89 编译器,基本就能跑。
Wren 也讲兼容,但底线是 C99 或 C++98,且必须 IEEE 双精度浮点。
这排除了少量古董硬件,却换来 NaN 装箱、计算型 goto 等提速技巧。
相似文章
2026 年 WebAssembly 运行时性能
本文使用 libsodium 加密库对多种 WebAssembly 运行时(WAVM、WasmEdge、WAMR、wasm2c、Wasmer、Wasmtime、Wazero、Node、Bun)进行了性能基准测试,比较了 2024、2025 和 2026 年的版本。结果显示,WAVM、WasmEdge(AOT)、WAMR(AOT)、wasm2c、Wasmer 和 Wasmtime 在 CPU 密集型加密任务中实现了接近原生的性能,而 wide_arithmetic 指令对加密代码有益。
Lunacy - 具备惰性基本块版本化与JIT的Lua 5.1解释器
Lunacy 是一个用Rust编写的Lua 5.1解释器,实现了惰性基本块版本化和即时编译器,详细信息见技术博客文章。
如何构建高性能动态语言解释器
本文是一篇深度技术分析,详细阐述了如何针对动态类型语言 Zef 优化基于抽象语法树(AST)遍历的解释器。通过改进值的内部表示、引入内联缓存、优化对象模型及其他多项加速技术,最终实现了 16 倍的运行速度提升,使 Zef 的性能达到了可与 Lua、QuickJS 和 CPython 相媲美的高水准。
Rust语言的性能
本次演讲分析了Rust相较于C++的性能优势与劣势,提供了基准测试和最佳实践。附有幻灯片和阅读材料。
Show HN: Nimic – 纯Python作为系统语言并支持AOT编译
Nimic是一个纯Python模块,允许使用Python DSL编写可AOT编译的代码,该DSL可转译到Nim,在保持有效Python的同时实现C级性能。