博客 / 詳情

返回

MicroQuickJS:為極致資源而生的嵌入式JavaScript革命

當全球的開發者仍在為V8、SpiderMonkey等瀏覽器引擎的性能差異而爭論不休時,一位曾用一台普通台式機打破超級計算機圓周率計算紀錄的程序員,已將目光投向了另一個截然不同的戰場。2025年12月,被譽為“程序員之神”的Fabrice Bellard發佈了他的最新開源項目——MicroQuickJS。

這並非對現有JavaScript引擎的又一次性能優化,而是一次徹底的範式轉移。它的目標是讓完整的JavaScript運行時,在僅擁有10KB RAM和約100KB ROM的微控制器上平穩運行。這意味着,未來運行在你智能手錶、温控器甚至工業傳感器上的邏輯,可能不再是冰冷的C語言固件,而是靈活、動態的JavaScript腳本。

一、誕生於傳奇之手:為何是Fabrice Bellard?

要理解MicroQuickJS的雄心,必須先了解其創造者。Fabrice Bellard的名字是開源世界一座不朽的豐碑。他於2000年發佈的FFmpeg,如今是幾乎所有音視頻軟件的基石;2005年創造的QEMU,極大地推動了虛擬化技術的普及。他的成就不僅限於工程,更在於其挑戰極限的思維——2009年,他僅用一台價值3000美元的PC,將圓周率計算到近2.7萬億位,打破了當時超級計算機保持的紀錄。

在2019年推出支持完整ES2023標準、性能卓越的QuickJS引擎後,Bellard再次將目光投向“小處”。他看到了一個被主流JavaScript世界忽視的廣闊領域:數以億計的資源極端受限的嵌入式設備。MicroQuickJS正是他“技術普惠性”哲學的又一次實踐,旨在讓最底層的硬件也能享受高級腳本語言帶來的開發效率。

二、核心設計哲學:為“生存”而做的減法

MicroQuickJS並非QuickJS的“迷你版”或“閹割版”,而是一個基於全新設計的、獨立的代碼庫,與QuickJS共享部分解析器代碼,但內核機制截然不同。其一切設計的出發點,都是為了在確定性、安全性和極低內存開銷之間取得精妙平衡。

1. 極致的靜態化與ROM化
在嵌入式系統中,ROM(閃存)資源相對豐富,而RAM(運行內存)極為寶貴。MicroQuickJS將這一特性發揮到極致。其整個引擎(包括C庫)在ARM Thumb-2架構下僅需約100KB ROM空間。更關鍵的是,標準庫(如Math、Array)在編譯階段就被轉換為C結構體,直接固化到ROM中。引擎初始化時,這些庫幾乎以“零成本”加載,無需在RAM中創建對象,從而實現了閃電般的啓動速度。

2. 嚴格到骨子裏的JavaScript子集
MicroQuickJS支持的JavaScript語法大致在ES5範圍內,但執行着比標準“use strict”更嚴苛的規則。這不是為了刁難開發者,而是嵌入式環境下生存的必需:

  • 禁止數組“空洞”a[10] = 1(當數組長度為0時)會直接拋出TypeError。因為稀疏數組會浪費大量內存用於填充undefined。如需不連續存儲,必須使用對象{}
  • 僅支持間接eval:禁止eval('code'),只允許(1, eval)('code')這種全局作用域執行的模式,徹底阻斷其對局部作用域的訪問,保障封裝性和安全性。
  • 禁用with語句:消除作用域的不確定性。
  • 精簡的標準庫Date對象僅支持Date.now();字符串的toLowerCase/UpperCase方法僅處理ASCII字符;正則表達式的大小寫摺疊同樣限於ASCII。這種“該省則省,該給就給”的策略,精準地服務於嵌入式應用的常見場景。

3. 革命性的內存管理:追蹤式垃圾回收
與大多數輕量級引擎(包括QuickJS)採用引用計數不同,MicroQuickJS大膽採用了追蹤式垃圾回收器。此舉能自動處理循環引用這個引用計數的噩夢,並支持內存壓縮,從根本上避免內存碎片化。
代價是,對象在GC運行時地址可能會“搬家”。為此,MicroQuickJS的C API設計了一套獨特的JSGCRef引用機制。開發者不能長期持有JS對象的直接指針,而必須通過JS_PushGCRef()獲取一個受保護的引用,該引用會在對象移動時自動更新,使用完畢後需調用JS_PopGCRef()釋放。這種“以開發複雜度換取運行時極致效率”的設計,是MicroQuickJS能在10KB內存中管理複雜對象關係的關鍵。

三、三大顛覆性應用場景

MicroQuickJS的出現,正在打開以下幾扇此前緊緊關閉的大門:

1. 嵌入式設備動態邏輯升級
對於無法支持OTA(空中下載)或文件系統的低端設備,傳統上任何邏輯修改都需重刷整個固件。利用MicroQuickJS,開發者可以將業務邏輯用JavaScript編寫,在PC上預編譯為字節碼(使用./mqjs -o firmware.bin logic.js命令),然後將這個極小的.bin文件像數據一樣燒錄進芯片的固定地址。設備上電後,引擎加載並執行這段字節碼即可。這意味着,無需觸動底層的C驅動固件,僅通過替換字節碼就能實現業務邏輯的靈活迭代,極大地降低了維護成本和風險。

2. 安全可靠的代碼沙盒
獨立開發者Simon Willison在項目發佈後立即進行了一項探索:將MicroQuickJS用作執行不可信代碼(如用户提交或LLM生成)的安全沙盒。他發現,MicroQuickJS天生適合此角色:

  • 硬性資源限制:可通過--memory-limit 10k參數嚴格限制內存,從根本上杜絕內存耗盡攻擊。
  • 執行時間可控:引擎支持設置中斷處理器,即使在正則表達式回溯等複雜操作中也能強制執行時間限制。
  • 純淨的運行環境:默認不提供任何文件系統、網絡訪問等危險API。
    Willison成功將其編譯為WebAssembly,並創建了交互式網頁 playground,其加載體積僅303KB,遠小於完整版QuickJS的2.28MB。這為雲端函數、插件系統、在線代碼評測等場景提供了一個極其輕量且安全的新選擇。

3. 超低功耗物聯網節點
在由電池供電、RAM僅KB級別的傳感器節點中,MicroQuickJS使得用高級語言實現複雜數據採集、過濾和通信協議成為可能。開發者可以用更高效的JavaScript描述設備行為,同時通過其嚴格模式避免不可預知的運行時錯誤,保障設備在野外數月甚至數年的穩定運行。

四、與QuickJS的定位分野

很多人會問,既然有了QuickJS,為何還需要MicroQuickJS?答案在於二者服務的是不同的“戰場”,形成了完美的互補:

  • QuickJS是“常規軍”:面向通用嵌入式環境(如樹莓派)、桌面腳本工具等,支持ES2023等現代特性,內存佔用在數百KB以上,追求在較小體積下提供完整的JavaScript體驗。
  • MicroQuickJS是“特種兵”:專攻RAM低於32KB、ROM小於256KB的極端環境,如單片機、傳感器、ECU單元。它為了極致的資源效率,主動犧牲了部分語言特性和動態靈活性。

五、快速上手指南

體驗MicroQuickJS的極致簡約非常簡單:

  1. 獲取與編譯

    git clone https://github.com/bellard/mquickjs.git
    cd mquickjs
    make

    編譯後即得到可執行文件mqjs

  2. 直接運行JS

    # 運行腳本
    ./mqjs hello.js
    # 啓動交互式REPL
    ./mqjs -i
    # 在10KB內存極限下挑戰運行曼德博集計算
    ./mqjs --memory-limit 10k tests/mandelbrot.js
  3. 嵌入C項目:核心API設計極為精簡。以下代碼展示瞭如何在一塊靜態內存緩衝區中啓動引擎:

    #include "quickjs.h"
    uint8_t mem_buf[8192]; // 使用8KB靜態內存塊
    JSContext *ctx = JS_NewContext(mem_buf, sizeof(mem_buf), &js_stdlib);
    // ... 加載並執行JS代碼
    JS_FreeContext(ctx); // 注意:此調用主要用於觸發對象析構,非釋放系統內存

    整個引擎運行在用户提供的這塊mem_buf中,無需動態內存分配,完美契合無操作系統或RTOS的環境。

結語:小體積背後的大視野

MicroQuickJS的發佈,其意義遠不止於一個“更小的JS引擎”。它代表着一種技術思潮的迴歸與突破:在算力爆炸、軟件日益臃腫的時代,依然有人專注於為最受限的環境賦予最強大的能力。它打破了“JavaScript屬於瀏覽器和服務器”的思維定式,將這門語言的活力注入到物理世界的毛細血管之中。

正如Bellard一貫的風格,MicroQuickJS沒有炫目的宣傳,只有實實在在的代碼和令人震撼的性能指標。它或許不會成為Web開發的主流,但它正在悄然開啓一個新時代:未來,當你與身邊最微小的智能設備交互時,其背後可能正運行着一段優雅而高效的JavaScript代碼。這,正是技術普惠最深刻的體現。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.