WebAssembly-to-C 仍能打平原生執行環境
2026 年的 libsodium 基準顯示,WebAssembly-to-C 在加入 wide arithmetic 後,仍能和 Wasmer、Wasmtime 這類原生執行環境正面競爭。

2026 年的 libsodium 基準顯示,WebAssembly-to-C 在加入 wide arithmetic 後,仍能和 Wasmer、Wasmtime 這類原生執行環境正面競爭。
Frank DENIS 重新跑了一次 2026 基準測試。結果很直接,WebAssembly 編成 C 之後,速度還是能跟專用 runtime 正面對打。更意外的是,這件事發生在 WebAssembly runtime 已經有更好的 compiler、lowering,還多了更寬的指令支援之後。
這次測的是 Frank DENIS、Wasmer 7.1.0、Wasmtime 46.0.0,還有 WABT 裡的 wasm2c 路徑。DENIS 也把 wide arithmetic proposal 補進自己的 wasm2c fork,再用 zig cc 搭配 -O3 -march=native 編譯。
| 項目 | 數值 | 意義 |
|---|---|---|
| Wasmer 版本 | 7.1.0 | 比較用 runtime 之一 |
| Wasmtime 版本 | 46.0.0 | 比較用 runtime 之一 |
| 建置特徵 | lime1 + simd128 + wide_arithmetic | 所有版本共用的功能集合 |
| 編譯器 | zig cc -O3 -march=native | 最後的原生 C 編譯路徑 |
| 記憶體量測 | 15 次、取 median RSS | 看冷啟動記憶體用量 |
這次基準測試到底改了什麼結論
訂閱 AI 趨勢週報
每週精選模型發布、工具應用與深度分析,直送信箱。不定期,不騷擾。
不會寄垃圾信,隨時可取消。
DENIS 自己也說,他原本以為 WebAssembly-to-C 的優勢會慢慢縮小。這個直覺很合理。runtime engine 一直在進步,JIT 能做的優化,也比單純 transpiler 多。

但 2026 的數字往另一邊走。這次測的是 libsodium,而 wasm2c 在加入 wide arithmetic 後表現很穩。文中的結果顯示,median 跟 Wasmer 打平,geomean 只有 Wasmer 的 0.887x,也只有 Wasmtime 的 0.814x。
這代表一件很實際的事。當 WebAssembly module 事先已知,而且可以先編譯成 C,最後交給成熟的 native compiler,表現還是很能打。這種路線沒有大家想像中那麼老派,反而很務實。
- Median 結果:與 Wasmer 打平
- Geomean runtime:wasm2c 為 Wasmer 的 0.887x
- Geomean runtime:wasm2c 為 Wasmtime 的 0.814x
- Benchmark 目標:libsodium
為什麼 C 路徑還活得很好
原因其實很簡單。輸出結果是普通 C。最後那段 codegen 交給成熟的 native compiler,不需要自己維護一套小型 backend。這種做法很土,但土得有效。
DENIS 也提到,wasm2c 補 wide arithmetic 沒那麼痛苦。它主要靠 compiler carry intrinsics,再加上 C 的 128-bit integer type。對工程師來說,這代表功能擴充不一定要把整個工具鏈翻掉。
還有一個常被忽略的優勢。WebAssembly runtime 會把 engine code、startup state、JIT machinery 一起帶進 process。C 編譯後的 module 不會。這種差異在短命工作負載上很明顯。
“The best WebAssembly runtime may still be no runtime at all.” — Frank DENIS
這句話很直白。當你已經有 module,而且不需要 runtime 服務時,多一層 engine 可能只是多一層成本。
記憶體才是很多人沒算進去的帳
DENIS 用 /usr/bin/time -v 看 cold process RSS,再取 15 次的 median。這種量法很適合看啟動成本,因為很多服務在真實環境裡根本不會一直熱著。

他也提醒了一個常見誤區。runtime 的成本可以被攤平。只要服務會長時間存活,或者會重複跑很多 module,engine 的固定開銷就沒那麼刺眼。
但如果是一次性工作,情況就變了。批次任務、短命 CLI 工具、部署環境很受限的系統,這些場景都會把 startup overhead 放大。這時候,C 路徑就很有存在感。
- 量測方式:
/usr/bin/time -v的 cold RSS - 每個配置執行:15 次
- 線性記憶體上限:64 MiB
- 主要成本來源:engine executable 與 startup state
所以這個結果不是在說 runtime 沒用。它是在說,當啟動成本被算進去,整個經濟模型就變了。
部署選擇也跟著改變
WebAssembly-to-C 會把部署目標換掉。目的機器不需要 WebAssembly runtime,只需要 C compiler 和足夠的 libc 支援。這讓它變成很傳統、也很實際的 portable 方式。
DENIS 也提到,編譯器本身現在就是選項。你可以用 clang 或 GCC。如果你在意不同的信任模型,還能考慮 Fil-C。如果你要的是驗證過的 code generation,CompCert 也在桌上。
這種彈性很少被拿來認真談。專用 runtime 給你單一執行模型。WebAssembly-to-C 則讓你自己選 compiler,再決定要速度、要安全,還是要形式化保證。
Wasmer 和 Wasmtime 還是有強項
DENIS 也沒有把 runtime 說死。他很清楚,WebAssembly-to-C 不適合動態載入不受信任的 code,也不適合 policy enforcement、preemption、fuel metering、component-model machinery,或共享 engine 的 multi-tenant 環境。
Wasmer 的 WASIX 很重要。它補了不少 WASI 還不完整的 POSIX 缺口。如果你要跑現成應用,這條路比 transpile 成 C 直接得多。
Wasmtime 則有 Component Model。它讓 WebAssembly 模組之間有型別化邊界,方便組合。DENIS 提到,理論上也能把 component 分開編成 C,但他沒有深入測。
- 適合 runtime:不受信任 code、policy、fuel、多租戶
- 適合 WebAssembly-to-C:已知 module、先編譯、短命任務
- Wasmer 強項:WASIX,補足 POSIX 類工作負載
- Wasmtime 強項:Component Model,適合 typed composition
這對工程師的實際意思
這份結果最有意思的地方,在於 WebAssembly 走了兩條路。runtime engine 變強了,compile-to-C 的路線也沒有掉隊那麼多。尤其 wide arithmetic 落地後,這條路在 cryptographic code 上還是很能打。
如果你現在要選 WebAssembly 方案,別先背口號。先看你需不需要 engine,會不會跑不受信任 code,還有 module 是否必須跨主機保持一致。答案如果偏向 runtime,就用 runtime。答案如果偏向控制權和精簡堆疊,WebAssembly-to-C 仍然值得放進選項。
我會把這篇的結論講得更直接一點:很多團隊其實不需要 runtime,只是習慣先裝 runtime。下一次做技術選型時,先問自己一件事,你的 WebAssembly 工作負載,有多少真的需要 engine 提供的那些額外服務?
台灣團隊可以怎麼看這件事
如果你在做後端服務、CLI 工具,或是要把一段安全敏感的邏輯塞進產品裡,這篇很值得記下來。WebAssembly 常被包裝成「到處都能跑」,但真正落地時,啟動時間、記憶體、部署包大小,常常比理論更重要。
台灣很多團隊的部署環境都很現實。容器數量有限,CI/CD 要快,機器規格也不一定豪華。這時候,少一個 runtime,常常比多一個優化 flag 更有感。先把成本攤開,再談架構,會比直接選最潮的方案更省事。