Hacker News 中文摘要

RSS订阅

WASM编写笔记 -- Notes on Writing WASM

文章摘要

作者分享使用Rust编写Wasm的经验,建议通过引用传递数据、优先使用Rc>而非可变引用、避免为导出类型实现Copy特性,并推荐wasm-bindgen工具。虽然承认该工具存在不足,但作者提供了实用模式以改善开发体验。

文章总结

WebAssembly 开发实践笔记

作者分享了几年来使用 Rust 编写 WebAssembly(Wasm) 的经验总结,重点介绍了如何优化与 wasm-bindgen 工具协作的开发模式。

核心建议

  1. 引用传递优先:通过 &reference 传递跨边界数据
  2. 避免可变引用:使用 Rc<RefCell<T>>Arc<Mutex<T>> 替代 &mut
  3. 类型设计
    • 不要为导出类型派生 Copy trait
    • 对集合中的跨边界类型使用 wasm_refgen
    • Rust 导出类型添加 Wasm 前缀,JS 端使用无前缀名称
    • JS 导入类型添加 Js 前缀
  4. 错误处理:为所有 Rust 导出错误类型实现 From<YourError> for JsValue

技术细节

内存模型差异

JavaScript 和 Rust 采用不同的内存管理方式: - JavaScript:垃圾回收、可重入、异步 - Rust:显式所有权、借用规则

类型命名规范

  • 基本类型:实现 IntoWasmAbi 的原始类型
  • Rust 导出类型:添加 Wasm 前缀(如 WasmFoo
  • JS 导入类型:添加 Js 前缀(如 JsCharacter

引用传递的重要性

直接消费跨边界值会导致 JS 端句柄失效。推荐使用 Rc<RefCell<T>> 等内部可变性模式。

集合处理技巧

通过 duck typing 解决 wasm-bindgen 对集合类型的限制: 1. 使导出类型易于克隆 2. 暴露命名空间化的克隆方法 3. 通过 JS 接口导入该方法 4. 实现便捷的类型转换

错误处理优化

将 Rust 错误转换为 js_sys::Error 以保留错误信息: rust impl From<WasmError> for JsValue { fn from(err: WasmError) -> Self { let js_err = js_sys::Error::new(&err.to_string()); js_err.set_name("ErrorType"); js_err.into() } }

实用技巧

  • 构建信息打印:在启动时输出 Git 哈希和构建状态,便于调试
  • wasm_refgen 工具:简化引用生成代码的编写
  • 避免 Copy trait:防止意外复制资源句柄

总结

作者强调明确处理 Wasm 边界的重要性,建议采用清晰的命名约定、引用传递和 duck typing 等技术来克服 wasm-bindgen 的限制,从而提升 Rust+Wasm 的开发体验。

注:本文内容基于作者个人实践经验,可能存在更优解决方案。作者对 wasm-bindgen 维护者的工作表示敬意。

评论总结

以下是评论内容的总结:

1. 对WASM的失望与批评

  • 内容不符预期:多位用户指出文章标题与实际内容不符,期待的是直接编写WASM的指南,而非Rust工具链相关内容。
    引用
    "I was hoping to find Notes on Writing WASM, instead I found stuff for writing Rust to target WASM" (评论1)
    "I expected an article about writing code directly in wasm. Title is bit missleading" (评论9)

  • 复杂性与工具链问题:批评WASM生态过于依赖Rust工具链,且自动绑定生成(如wasm_bindgen)增加了不必要的复杂性。
    引用
    "Yes wasm is basically a rust thing at this point unfortunately" (评论5)
    "It adds an incredible amount of complexity and bloat" (评论6)

  • 类型转换与性能损耗:指出WASM与JavaScript类型系统(如UTF-8与UTF-16)不匹配导致频繁转换,影响性能。
    引用
    "We need to constantly convert between them" (评论2)

2. WASM的定位与前景争议

  • 小众化担忧:部分用户认为WASM可能永远是小众技术,实际使用者极少。
    引用
    "wasm will remain a small niche... probably forever" (评论3)

  • 应用场景偏离初衷:批评WASM从高性能计算工具演变为通用沙箱方案,导致臃肿化。
    引用
    "Now it gets marketed as something to write sandboxed code/components for every language" (评论2)

3. 开发体验与语言对比

  • 多语言实践反馈:用户分享使用C++、Zig、Odin和Rust开发WASM游戏的体验,指出Rust的严格性在快速开发中成为障碍,而Odin体验最佳。
    引用
    "Rust is an authoritarian nanny state" (评论12)
    "Odin, I found surprisingly pleasant... Nicest I’ve seen by far" (评论12)

  • 工具改进建议:推荐实用工具(如tsify)提升类型安全,并建议手动设计C API而非依赖自动绑定。
    引用
    "A tool that’s great to have... is tsify" (评论8)
    "tunnel through a properly designed C API" (评论6)

4. 技术改进与未来展望

  • 规范与生态进步:肯定WASM规范清晰,且Firefox正推动更高层次的API接口提案。
    引用
    "I found the spec very clear and well-written" (评论11)
    "Firefox is pushing an early proposal to expose all the web apis directly to wasm" (评论14)

  • GC语言支持疑问:探讨GC语言(如Java)在WASM中的适用性是否改善。
    引用
    "Is anyone using WASM with GC languages?" (评论13)

总结呈现了WASM在工具链、类型系统、生态定位等方面的争议,同时包含开发者实践反馈和技术演进动态,观点较为平衡。