如果说Linus Torvalds因其创造的Linux和Git而闻名于世,那么在纯技术能力上,或许有一位程序员能与之比肩,甚至在某些方面更胜一筹。
浏览他的个人项目主页时,那种震撼感难以言表。他不仅开发了著名的模拟器QEMU和音视频处理库FFmpeg——仅这两项成就便足以让绝大多数程序员望尘莫及——他还涉足编写C编译器、OpenGL实现、LTE软基站、JavaScript引擎,成功让Linux在浏览器中运行,甚至创造了计算圆周率的世界纪录。
这意味着,这位大神在操作系统、模拟器、多媒体、计算机图形学、编译器、编程语言、通信乃至数学等多个顶尖领域自由穿梭,其创造力和产出效率令人惊叹。更不可思议的是,他编写的程序往往比其他同类程序小几个数量级,同时快几个数量级。
这或许就是天才的真实写照。他就是法国程序员法布里斯·贝拉(Fabrice Bellard)。
图1:法国天才程序员 Fabrice Bellard

贝拉有一个显著的特点:每当他开发出一个足以开创一个领域的杰出软件后,便会将其交给社区维护,自己则转身投入下一个全新的技术挑战。最近,他再次出手,带来了一个名为MicroQuickJS的开源项目。
这是一个面向嵌入式设备的JavaScript引擎。访问其项目主页会发现,MicroQuickJS引擎运行时仅需10KB内存即可编译和运行JavaScript程序。在如此苛刻的资源限制下,其运行速度却接近QuickJS(同样是贝拉编写的另一款轻量级JS引擎)。
仅仅10KB!想想Node.js、Chrome V8乃至Electron的庞大体积,这种极致的优化能力确实堪称恐怖。难怪Redis之父antirez曾感叹:如果这东西在2010年就出现了,Redis的脚本语言就不会是Lua,而是JavaScript!
图2:技术大神的思考瞬间

那么,MicroQuickJS为何能做到如此之小?其核心理念并非简单地“移植JavaScript”,而是从根本上“重新定义JavaScript在嵌入式设备上应有的形态”。
1. 一个精心裁剪的 ES5 “子集”
MicroQuickJS支持的并非我们熟悉的那个功能完备的JavaScript,而是一个被刻意约束的精简版本,其设计取舍极具针对性:
- 只支持严格模式(strict mode):摒弃历史包袱,使行为更简单、可预测,便于优化。
- 数组不允许有“空洞”:不允许类似
arr[100] = 1而前99项为空的写法。这使得数组可以用更紧凑的线性方式存储,避免内存浪费。
- 不支持直接eval:
eval会导致代码在运行时动态变化,是内存管理和性能优化的噩梦。直接移除后,引擎实现变得清爽许多。
- 日期功能极简:仅支持
Date.now()获取当前时间戳,不处理复杂的时区、格式化等历史包袱,满足嵌入式场景最核心的需求。
- 字符串大小写转换仅限ASCII:不支持完整的Unicode大小写映射,以此换取代码体积和内存占用的大幅降低。
这些限制看似“奇怪”,但都指向同一个目标:确定性、简单性、低内存消耗。
2. 垃圾回收:策略直接但极其高效
在内存仅几十KB的环境中,内存碎片化往往比内存不足更为致命。MicroQuickJS的垃圾回收(GC)策略非常硬核:采用追踪式与压缩式相结合的GC。
第一层:追踪式GC
引擎从一组“根对象”出发,标记所有仍可被访问到的对象,剩余的不可达对象则被一次性全部清理。这种方法无需在每个对象上维护引用计数,也无需担心循环引用问题。每个对象只需几个比特的标记信息,结构非常精简。
第二层:压缩式GC
更为彻底的是,存活下来的对象并不会留在原内存位置。在回收过程中,GC会将所有存活对象重新排列,紧密地“压缩”到一段连续的内存区域中。这彻底消除了内存碎片,使得后续的内存分配变得极其简单高效,对资源紧张的小型设备极其友好。
值得一提的是,MicroQuickJS完全不依赖系统的malloc,而是自己实现了一套内存分配器。这在嵌入式领域至关重要,因为你永远无法预知系统自带的内存分配器会暗中浪费多少宝贵的内存。
3. 极致的值与对象表示
这里展现了贝拉深厚的计算机基础功底和“炫技”时刻。
在MicroQuickJS中,一个JavaScript值(无论是数字、字符串、对象还是函数)在内存中统一只占一个CPU字长。在32位系统上,就是32位(4字节)。这意味着:所有值都能直接存入CPU寄存器,参数传递、赋值、类型判断等操作都变得极其高效,内存布局也非常规整。
对象结构被压缩到了理论极限。一个JavaScript对象最少只占用3个CPU字(在32位系统上为12字节),这几乎达到了实现一个对象所需信息的理论最小值,仅能存储对象的基本类型标识和指向其属性表的指针。
属性本身也并非“廉价”。每个属性至少占用3个CPU字。因此,在嵌入式环境中,“随意为对象动态添加属性”是一种非常奢侈的行为。这也从另一个角度解释了为何要在语言层面施加诸多动态性限制。
字符串的处理也另辟蹊径:内部存储采用更节省空间的UTF-8编码,但在外部接口上仍然呈现为JavaScript标准规定的UTF-16语义。做到了“存储时节省空间,运行时符合规范”。
4. 标准库“固化”进ROM
在许多JavaScript引擎中,启动时需要动态创建Object、Array、Math等大量内置对象,这些对象会常驻在RAM中。
MicroQuickJS换了一种思路:在编译时就将这些标准库对象预先生成好,作为只读数据直接“焊死”在程序的镜像文件中,存放于ROM(只读存储器)区域。运行时直接引用即可,无需再次创建和初始化。这带来了启动速度极快、RAM占用极低的巨大优势。
总而言之,在嵌入式世界里,JavaScript的设计哲学从“功能越全越好”转变为“够用就好,极致优化”。杰夫·阿特伍德(Jeff Atwood)那句著名的“Atwood定律”提到:“任何能够用JavaScript编写的应用程序,最终都会用JavaScript编写。”
图3:Atwood定律的呈现

现在看来,这条定律同样正在向嵌入式系统领域延伸。或许在不久的将来,我们将在各种传感器、智能家居设备以及可穿戴设备上看到JavaScript的身影。
回看法布里斯·贝拉本人,他异常低调,几乎不接受采访、不撰写文章或书籍。网络上只能找到他零星的只言片语,例如他曾说:“我经常会厌倦一直做同样的事情,所以我会时不时地改变一下方向。”
由于他在众多差异巨大的领域都取得了常人难以企及的、近乎不可思议的成就,甚至有人怀疑“Fabrice Bellard”并非一个真实的人,而是一个由多人共用的ID,用于发布开源实战项目。
但或许,贝拉之所以看起来像“一群人”,并非因为他不真实,而是因为我们早已习惯了需要庞大团队、精密路线图和漫长周期的工业化软件生产模式。突然遇到这样一位仿佛仍生活在“个人英雄主义时代”的程序员,他的出现方式总是如此独特:没有预热,没有宏大宣言,代码一经发布,世界便不得不承认——原有的技术规则已被改写。
这样的技术天才及其作品,对于整个开发者社区而言,无疑是珍贵而令人振奋的存在。