凌晨两点,OpenUI的工程师盯着火焰图,发现Rust写的解析器居然在拖后腿。
他们花了三个月把核心模块用Rust重写,编译成WASM(WebAssembly,一种浏览器内运行的二进制格式),理论上该快到飞起。结果线上数据显示:每次解析调用,真正跑Rust逻辑的时间只占零头。
瓶颈藏在JS和WASM的交界处——一个他们从未认真算过的"边界税"。
六层流水线:一个LLM DSL的变形记
OpenUI-lang解析器干的事不复杂:把大模型吐出的自定义DSL(领域特定语言),转成React组件树。但"实时"两个字把难度拉满了——它跑在流式输出的每一 chunk 上,用户看着字一个个蹦出来,延迟超过100ms就能感知卡顿。
流水线拆成六段,像工厂组装线:
Autocloser(自动补全器)最先接招。大模型输出到一半突然断了?它得秒补最小化的闭合括号、引号,让残缺的语法能过检。Lexer(词法分析器)跟着做单遍字符扫描,吐出带类型的token流。Splitter(分割器)把token切成"id = expression"的语句对。Parser(解析器)用递归下降法建AST(抽象语法树)。Resolver(解析器)inline所有变量引用,还要处理循环依赖检测。最后Mapper(映射器)把内部AST转成OutputNode格式,喂给React渲染器。
这套东西用Rust写,编译到WASM,逻辑上没毛病——Rust快,WASM接近原生速度,管道又够复杂。但上线后工程师发现,优化错了对象。
WASM边界税:藏在 memcpy 里的时间黑洞
他们画了一张调用流程图,真相刺眼:
JS世界喊一声wasmParse(input),先把字符串从JS堆拷贝到WASM线性内存——这里埋着第一次malloc+memcpy。Rust本体解析确实快,但完事后要serde_json::to_string()把结果序列化成JSON字符串。接着第二次malloc+memcpy,把JSON串搬回JS堆。最后V8跑JSON.parse(),反序列化成JS对象。ParseResult这才到手。
Rust解析本身从未是慢的部分。慢的是边界:拷贝进去、序列化、拷贝出来、再解析。四次过手,三次跨运行时。
工程师自然想到:让WASM直接返回JS对象,跳过JSON这步?他们集成了serde-wasm-bindgen,专干这事——把Rust struct转成JsValue直接丢回去。
结果更慢。
serde-wasm-bindgen的陷阱:细粒度跨边界是原罪
问题出在内存布局的根本差异。JS没法把WASM线性内存里的Rust struct字节直接当原生对象读——两个运行时用的完全是两套内存结构。
serde-wasm-bindgen要造JS对象,得递归地把Rust数据物化成真正的JS数组和对象。每次parse()调用,触发大量细粒度的跨运行时转换。对比JSON方案:serde_json::to_string()纯Rust内执行,零边界穿越,产出单一大字符串;一次memcpy进JS堆;V8的C++层JSON.parse单遍优化处理。
更少、更大、更优化的操作,碾压更多、更小、更碎片化的操作。
他们用FixtureJSON做基准测试,数字冰冷:
simple-table场景,JSON往返20.5ms,serde-wasm-bindgen 22.5ms,慢9%。contact-form场景差距拉大,61.4ms对79.4ms,慢29%。复杂数据结构下,"优化"成了负优化。
TypeScript重写:把边界税降到零
凌晨的会议结论干脆利落:删掉Rust,用TypeScript重写。
听起来像倒退——但边界税是固定成本,跟Rust多快无关。TS版本跑在V8里,没有JS↔WASM的内存拷贝,没有序列化反序列化,对象直接在堆上生成。六层流水线原样保留,逻辑一字不改,只是把执行环境统一了。
结果:整体提速3倍。
不是Rust不够快,是跨边界通信的税太重。当单次处理的数据量不大、调用频率极高时,"在正确的地方做正确的事"比"用最快的语言"更重要。
OpenUI团队把这段经历写进博客,标题带着自嘲的诚实。他们没否定Rust——如果解析器跑在服务端,批量处理大文件,WASM的边界税被摊薄,结论可能完全不同。但在浏览器里、流式场景下、每几十毫秒触发一次的调用模式里,TS赢了。
这个案例正在前端圈发酵。Next.js团队的人转发评论,WASM倡导者沉默,更多人开始重新测量自己项目的"边界税"——那些藏在架构图缝隙里、从未被计入成本的时间。
如果你也在浏览器里跑WASM,现在该去拉一张火焰图了。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.