章节摘要:浏览器是 Wasm 最繁忙的泊位,而 JavaScript 是这座码头的调度语言。本章讲清三件事:加载与实例化的 API 全貌、数据跨越边界的成本结构、Worker 与共享内存支撑的高级协作模式。读完你应当能设计出"边界调用少、数据搬运粗"的互操作架构——这是 Wasm 应用性能的分水岭。 一条主线:一次调用的过境手续 把视角压到一次最普通的调用上:页面里的按钮点击,触发了 JavaScript 对 Wasm 导出函数的一次调用。看似一步的动作,实际要走完一整套过境手续。 调用发起前,模块要先进港:字节经网络抵达、流式编译成模块对象、连同导入依赖一起实例化成实例——这条进港路线由第五章第一节展开。
章节摘要:浏览器是 Wasm 最繁忙的泊位,而 JavaScript 是这座码头的调度语言。本章讲清三件事:加载与实例化的 API 全貌、数据跨越边界的成本结构、Worker 与共享内存支撑的高级协作模式。读完你应当能设计出"边界调用少、数据搬运粗"的互操作架构——这是 Wasm 应用性能的分水岭。
把视角压到一次最普通的调用上:页面里的按钮点击,触发了 JavaScript 对 Wasm 导出函数的一次调用。看似一步的动作,实际要走完一整套过境手续。
调用发起前,模块要先进港:字节经网络抵达、流式编译成模块对象、连同导入依赖一起实例化成实例——这条进港路线由第五章第一节展开。调用发生时,参数若不是数字就要过海关申报:字符串要编码进线性内存、对象要走引用信封、批量数据要按约定布局直接共享——这是第二节的成本账本。计算完成,结果按原路返回,回调则经由函数表反向穿越边界——仍是第二节与第三章表模型的知识兑现。当计算量升级到秒级,主线程的渲染预算被挤占,调用就要搬进后台线程的工位,共享内存让数据免于二次搬运——第三节的高级集成接手这段。一条主线穿起三节,本质都是在回答同一个问题:边界上放什么、怎么放、放多频繁。
5.1 WebAssembly JavaScript API盘点进港与调度的全部手续:编译与实例化的两条路径(一次性和流式)、Module 与 Instance 两大对象、Memory、Table、Global 三个可共享的运行时资源,以及各类报错对象的身份识别。这一节是后续一切的词汇表。
5.2 数据传递机制是全章的账本核心。数字参数近乎免费;字符串要过编码与解码两道闸;结构体靠内存布局对齐;大块数据靠共享视图零拷贝。本节用基准对比把每条通道的成本摆上台面,并给出回调(宿主函数被模块反向调用)的正确姿势——它是最贵的一条通道,很多人在不知情的状态下把它用成了性能黑洞。
5.3 高级 Web 集成处理计算升级后的场面:Web Worker 提供后台工位,SharedArrayBuffer 与 Atomics 提供跨线程的共享内存与同步原语(也是第六章多线程提案的浏览器地基);Service Worker 让模块字节的缓存策略与页面解耦;OffscreenCanvas 让渲染循环整体搬进后台。本节以一个"主线程只管交互、Worker 承包计算"的标准架构收尾。
本章的拐点是一条被反复验证的工程定律:Wasm 应用的性能上限,往往不取决于计算本身,而取决于边界设计。计算再快,若每个图元、每条记录都要单独过一次边界,调用开销就会反客为主。反过来说,把数据批量化、把互调粗粒度化之后,哪怕算法相同,整体吞吐也常有台阶式跃升——第一章的场景判断标尺,在这里变成了可操作的设计原则。
第二个结论关于心智模型:不要把 Wasm 实例当成"另一个进程"——它与 JavaScript 共享线程、共享内存、共享事件循环,边界是逻辑的而非物理的。真正的物理边界出现在 Worker 与主线程之间,那里才是需要考虑并发与同步的地方;把这两层边界混为一谈,是互操作 bug 的高产来源。
浏览器泊位之外,Wasm 的航线正在向服务端与系统级场景延伸。下一章盘点那些正在改写航线的扩展提案:多线程、SIMD、垃圾回收、WASI 与组件模型——本章的 SharedArrayBuffer 正是其中的第一站。