WebAssembly
WebAssembly的目标并非取代Web上的JavaScript, 而是与JavaScript互相补充.
WebAssembly导出的函数在JavaScript被视作使用native code的函数.
WebAssembly导出的函数在JavaScript被视作使用native code的函数.
-
由于需要从JavaScript侧暴露外部函数给WASM调用, 加上数据类型的转换/序列化/复制成本,
在WASM侧调用Web API的效率 比JavaScript慢得多 , 调用的次数越多越慢, 非数值类型数据传递得越多越慢.
这也导致了WASM的最佳使用方法是用WASM补充JavaScript的计算性能, 而不是完全由WASM编写程序.
在未来, 通过externref/anyref和更好的WASM接口设计, 有望显著改善WASM调用Web API的速度 . -
内存模型非常简单, 以至于它甚至无法销毁掉申请的内存, 内存只能增长而不能缩小:
https://github.com/WebAssembly/design/issues/1397 -
尽管wasm很快, 但相比真正的本机代码, 它还是有很多的性能损失(本机代码的速度是wasm的1.75倍以上).
https://nickb.dev/blog/wasm-and-native-node-module-performance-comparison/
在少数情况下, wasm可能会比优化过的JavaScript代码还慢.
根据 Zaplib的测试 , 在实际使用中wasm往往只比预热过的JavaScript代码快一倍, 因为实际项目并不总是大量使用CPU密集型操作. -
虽然WebAssembly支持将i64类型转换为BigInt(JavaScript不支持i64), 但WebAssembly本身并不支持BigInt.
因此, JavaScript无法传BigInt作为参数, 如果要处理大整数, 则被迫传字符串, 然后由WebAssembly这一侧将字符串转换为自己的BigInt实现,
这无疑会造成很多开销. -
当前导入WASM模块的方式不是跨平台的, Web和Node.js使用不同的导入API.
有望在WASM支持作为ECMAScript模块使用时得到改进 . -
只支持32位, 可利用的最大内存为4G.
64位可能会在未来支持. -
文件体积很大, 一个用Rust编译出来的WASM文件至少也有10KB.
-
无法零复制共享内存 , 这使得很多高性能任务无法高效率完成, 例如发送ArrayBuffer或共享SharedArrayBuffer.
https://github.com/WebAssembly/design/issues/1162
https://github.com/WebAssembly/design/issues/1231 -
WASM的多线程目前处于提案状态.
https://github.com/WebAssembly/threads
WASM采用了一种相当奇怪的交互方式, JavaScript与WASM之间的调用只支持传递数值类型(整数和浮点数), 不支持字符串等常见的高级类型.
这导致两者之间需要传递高级类型的数据时, 实际上需要共享一个缓冲区, 然后传递对应的指针(即缓冲区内的偏移量), 再由需要的一方将其视作对应的高级类型来处理.
举例来说, 字符串传递时传递的不是字符串, 而是传递共享缓冲区的指针和长度, 再由需要字符串的一方将其识别为字符串.
举例来说, 字符串传递时传递的不是字符串, 而是传递共享缓冲区的指针和长度, 再由需要字符串的一方将其识别为字符串.
WebAssembly的内存指的是一块分配给WebAssembly的线性内存空间, 其本质是一块可增长的连续无符号字节缓冲区.
"线性内存"又称作"平面内存模型(Flat Memory Model)", 这被认为是接口最简单, 性能最好, 复杂度最小的内存模型.
"线性内存"又称作"平面内存模型(Flat Memory Model)", 这被认为是接口最简单, 性能最好, 复杂度最小的内存模型.
JavaScript可以共享给WebAssembly可调整大小的ArrayBuffer.
像wasm-bindgen这样的工具会自动抽象线性内存来平滑JavaScript与WebAssembly的访问.
像wasm-bindgen这样的工具会自动抽象线性内存来平滑JavaScript与WebAssembly的访问.
在WebAssembly里, 像函数指针这样的引用出于安全性/可移植性/稳定性等原因, 不能存储在线性内存空间中.
作为替代, 这类不可存储在线性内存中的数据被存储在"表(table)"里, 目前只有函数引用被存储在表里, 未来可能增加新的元素, 比如线程.
作为替代, 这类不可存储在线性内存中的数据被存储在"表(table)"里, 目前只有函数引用被存储在表里, 未来可能增加新的元素, 比如线程.
全局变量是在JavaScript侧创建的, 由WebAssembly使用的变量, 在多个WebAssembly模块之间可以共用.
https://github.com/WebAssembly/WASI
一个建立在WASM上的, 用于系统编程的接口.
本质上, 它是为了创建一个对任何可以编译到WebAssembly的语言都可以使用的系统库.
本质上, 它是为了创建一个对任何可以编译到WebAssembly的语言都可以使用的系统库.
如果WASI能够流行, WebAssembly会发展为一种公共的中间语言, 编程语言不再以平台为编译目标开发程序, 而是只以WebAssembly为编译目标来开发程序.
毫无疑问, 这将彻底颠覆整个程序设计领域的生态环境.
毫无疑问, 这将彻底颠覆整个程序设计领域的生态环境.
这是WASM自己的垃圾回收提案, 用于在不移植虚拟机的情况下将依赖于GC的编程语言移植到WASM上.
这降低了让编程语言支持WASM的难度, 更好地支持WASM的平台无关性.
这降低了让编程语言支持WASM的难度, 更好地支持WASM的平台无关性.
一种以S表达式表示的WebAssembly格式.
可以从wat文件生成wasm文件.
一般将其视作WebAseembly的"汇编代码".
一般将其视作WebAseembly的"汇编代码".
一种以二进制表示的WebAssembly格式.
理所当然的, 体积相比wat格式较小, 因此是主要被使用的格式.
最受欢迎的WASM运行时.
第二受欢迎的WASM运行时.
最受欢迎的WebAssembly语言, 大部分WASM程序都是通过Rust编写的.
Rust生态环境中主要的WebAssembly CLI.
wasm-pack build
的默认输出结果是整个npm包, v0.11.2以后可以通过
--no-pack
选项阻止此行为.
JavaScript代码生成器, 当需要使用
js-sys
,
web-sys
等JavaScript环境的绑定时, 需要使用此项目.
https://github.com/rustwasm/wee_alloc
一个可选的WASM内存分配器, 注重于删除不必要的Rust基础设施来减小WASM模块体积, 但会影响运行速度.
对于只在初始化时进行动态内存大小分配, 之后就没有再进行分配的程序有用.
一个不自以为是的WebAssembly CLI.
用Rust的WASM前端Web应用框架.
有很多stars, 但性能不理想, 即使相比React都还有相当大的距离:
https://github.com/yewstack/yew/issues/5
https://github.com/yewstack/yew/issues/5
Rust侧, JavaScript环境的绑定.
Rust侧, Web环境的绑定.
对
js-sys
/
web-sys
的重新封装, 提供更好的人体工学.
受欢迎程度仅次于Rust的原生WebAssembly语言, 但市场份额被Rust挤占得相当厉害, 份额从2022年开始大幅下降.
与TypeScript的区别:
-
AssemblyScript只有
null
, 没有any
和undefined
. -
不支持union, 只支持泛型.
-
不支持对象字面量和数组字面量.
-
AssemblyScript使用自己的标准库.
-
访问宿主环境需要宿主配合, 无法直接访问.
-
非null数组的成员需要手动初始化后才能访问.
-
AssemblyScript支持运算符重载, 顶级装饰器.
-
数组排序基于数值而不是字符串.
-
缺乏反射, 包括
Object.keys
这样的方法无法在AssemblyScript里支持.
特点:
-
API与JavaScript高度相似.
-
允许手动申请和回收堆内存.
-
支持动态数组和静态数组.
-
自动内存管理.
-
缺少像Rust的wasm-bindgen这样的东西, WASM与JavaScript代码的沟通依赖于手动编写声明和设置导出, 用户体验极差.
-
不支持传递任意JavaScript对象至AssemblyScript.
https://github.com/AssemblyScript/assemblyscript/issues/1620
在某种程度上, WASM anyref/externref特性的支持能解决此问题, 但该特性在AssemblyScript里仍处于实验阶段. -
相比Rust这样成熟的语言, 性能较差.
在一些基准测试里, 差别可以扩大到2倍. -
AssemblyScript还未实现闭包.
https://github.com/AssemblyScript/assemblyscript/issues/798