Wren 编程语言的性能表现

Lobsters Hottest 工具

摘要

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 运行时性能

Lobsters Hottest

本文使用 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 指令对加密代码有益。

如何构建高性能动态语言解释器

Hacker News Top

本文是一篇深度技术分析,详细阐述了如何针对动态类型语言 Zef 优化基于抽象语法树(AST)遍历的解释器。通过改进值的内部表示、引入内联缓存、优化对象模型及其他多项加速技术,最终实现了 16 倍的运行速度提升,使 Zef 的性能达到了可与 Lua、QuickJS 和 CPython 相媲美的高水准。

Rust语言的性能

Lobsters Hottest

本次演讲分析了Rust相较于C++的性能优势与劣势,提供了基准测试和最佳实践。附有幻灯片和阅读材料。