文章摘要
Jarred-Sumner提交了一个为JavaScriptCore添加共享内存线程的实验性PR,允许新线程在同一堆中共享对象,无需结构化克隆或消息传递。目前并行JavaScript执行已通过四个JIT层且无全局锁,但尚未完成,仍需清理线程消毒器、模糊测试和基准测试优化。
文章总结
好的,作为一名专业的中文编辑,我将对您提供的英文内容进行中文重述。我会保留核心细节,同时删减与文章主题(即该Pull Request的技术内容)无关的界面元素和冗长的自动化评论。
标题:为JavaScriptCore实现共享内存线程(实验性,尚未完成)
核心内容:
这是一个为JavaScriptCore(JSC)引擎添加共享内存线程功能的Pull Request。其核心思想是,通过 new Thread(fn) 创建一个新线程,该线程与主线程共享同一个堆(heap)和对象。这意味着,你不再需要通过结构化克隆、消息传递或 SharedArrayBuffer 来在线程间共享数据,而是可以直接共享对象本身。
当前状态: 并行JavaScript代码已经可以在所有四个JIT(即时编译)层级上运行,且没有全局锁。线程测试套件已通过。但项目尚未完成,还需要进行线程清理、模糊测试、性能优化和长时间稳定性测试。此PR的目的是让设计和代码可以被审阅和讨论,它可能永远不会被合并。
API 设计:
- 创建线程:
new Thread((a, b) => { return expensive(a, b); }, x, y);函数是一个闭包,可以访问其作用域内的变量、导入和类。 - 等待结果:
t.join()阻塞等待并返回函数值或抛出异常;t.asyncJoin()以Promise形式返回,不会阻塞。 - 同步原语: 提供了
Lock、Condition、ThreadLocal等标准同步工具。 - 扩展的 Atomics:
Atomics.*操作从类型化数组扩展到了普通对象属性,例如Atomics.load(obj, "k")。 - 线程限制:
Thread.restrict(obj)可以将对象固定到特定线程,防止其他线程访问。
核心优势与示例:
- 真正的对象共享: 无需序列化。例如,一个并行
map操作可以直接将结果写入共享数组,无需分块和合并。 - 共享缓存: 一个
Map对象可以被所有线程直接访问,无需通过消息传递或手动在SharedArrayBuffer上实现哈希表。 - 简单取消: 通过一个共享的布尔值对象即可实现线程取消,无需复杂的终止协议。
- 实时进度: 线程可以直接更新一个共享的进度对象,主线程直接读取即可,无需事件协议。
- 阻塞式交接: 支持使用
Condition变量进行线程间的阻塞式握手,这在传统的Worker模型中是无法实现的。 - 单一全局对象和模块图: 所有线程共享同一个
globalThis、Array、Object.prototype以及已执行的模块图。这意味着x instanceof Foo在所有线程上都为真,且创建新线程的成本远低于创建Worker。
性能开销预期:
- 不共享的代码: 开销几乎为零(<0.5%)。
- 共享对象上的写操作: 首次跨线程写操作会触发对象转换,后续访问会变慢(约7倍)。
- 每个线程的内存: 约150KB-1MB(繁忙时),远低于Worker的5-15MB。
设计基础:
该实现基于Filip Pizlo在2017年发表的论文《Concurrent JavaScript: It Can Work!》。其核心机制包括:
- TID标记的扁平蝴蝶结(Butterflies): 对象存储带有拥有线程的ID,同一线程访问自己的对象速度不变。
- 分段蝴蝶结: 当另一个线程写入时,对象会转换为分段存储,以实现无锁读取和安全的并发调整大小。
- 每对象单元锁: 用于需要互斥的慢路径。
- 过渡/写入线程局部监视点: JIT编译器会推测对象操作是线程局部的,当发生跨线程操作时,会触发重新编译。
当前进展与挑战:
- 阶段1(已完成): 实现了所有底层机制,但JavaScript执行仍在一个全局锁(GIL)下进行,用于确定性测试。
- 阶段2(进行中): 移除全局锁,实现真正的并行。这涉及处理栈溢出检查、异常状态、停止世界协议、OSR退出等大量单线程假设问题。
- 可扩展性测试: 在一个文档索引和查询引擎的基准测试中,JavaScript在16和32线程上的性能超过了Java,但在处理字符串和Map等高级对象时,性能差距较大(约13倍于Java),这主要是由JS对象模型的开销(如BigInt、字符串查找)造成的,而非线程机制本身。
总结:
这个PR为JavaScript提供了一种全新的多线程模型,允许线程共享堆和对象,从而能够直接实现许多在传统Worker模型中难以实现的并发模式。它是一项雄心勃勃的工程,虽然尚未完成,但其设计和代码已经展示了巨大的潜力。
评论总结
根据评论内容,主要围绕Bun项目提交的270k行LLM生成代码PR展开讨论,观点分歧明显:
支持/乐观观点(评分较低): - 认为这是TypeScript运行时创新的重要尝试,有望实现多线程数据库等应用(评论6、8) - 肯定LLM使大规模原型实验成为可能,证明技术可行性(评论17) - 赞赏Bun的文档和生态系统完整性(评论10)
质疑/批评观点(占多数): - 代码质量与可靠性:批评PR描述明显是未编辑的LLM输出,过度使用em-dash等格式(评论4、5、25),认为AI不擅长多线程代码(评论27) - GC问题:指出并行垃圾收集是最大难点,当前方案使用stop-the-world GC会严重影响延迟(评论13),引用Firefox早期多线程JS因GC问题被移除的先例(评论12) - 信任与维护:认为1800文件变更的AI生成代码不可信任,强调运行时可靠性应"无聊"(评论18、28),指出Bun已有稳定性问题(评论30) - 伦理争议:批评依赖Anthropic的"盗窃"行为(评论9)
历史视角: - 引用Douglas Crockford观点,认为事件模型优于线程(评论14) - 指出JavaScript已有Worker+SharedArrayBuffer实现并发(评论26)
关键引用: - "A stop-the-world garbage collector will kill tail latency"(评论13) - "the most important feature for a language runtime is reliability... it should be boring"(评论28) - "I won't use it. I don't trust it."(评论18)