SharedArrayBuffer
SharedArrayBuffer 对象用于表示通用的原始二进制数据缓冲区,类似于 ArrayBuffer 对象,但它们可用于在共享内存上创建视图。与可转让的 ArrayBuffer 不同,SharedArrayBuffer 不是 可转让对象。
¥The SharedArrayBuffer object is used to represent a generic raw binary data buffer, similar to the ArrayBuffer object, but in a way that they can be used to create views on shared memory. A SharedArrayBuffer is not a Transferable Object, unlike an ArrayBuffer which is transferable.
描述
¥Description
要使用 SharedArrayBuffer 对象从集群中的一个代理程序共享内存到另一个代理程序(代理程序是网页的主程序或其 Web Worker 之一),需要使用 postMessage 和 结构化克隆。
¥To share memory using SharedArrayBuffer objects from one agent in the cluster to another (an agent is either the web page's main program or one of its web workers), postMessage and structured cloning is used.
结构化克隆算法接受 SharedArrayBuffer 对象和映射到 SharedArrayBuffer 对象的类型化数组。在这两种情况下,SharedArrayBuffer 对象都会传输到接收方,从而在接收代理中产生一个新的私有 SharedArrayBuffer 对象(就像 ArrayBuffer 一样)。然而,两个 SharedArrayBuffer 对象引用的共享数据块是相同的数据块,并且一个代理中的块的副作用最终将在另一个代理中变得可见。
¥The structured clone algorithm accepts SharedArrayBuffer objects and typed arrays mapped onto SharedArrayBuffer objects. In both cases, the SharedArrayBuffer object is transmitted to the receiver resulting in a new, private SharedArrayBuffer object in the receiving agent (just as for ArrayBuffer). However, the shared data block referenced by the two SharedArrayBuffer objects is the same data block, and a side effect to the block in one agent will eventually become visible in the other agent.
const sab = new SharedArrayBuffer(1024);
worker.postMessage(sab);
共享内存可以在工作线程或主线程中同时创建和更新。根据系统(CPU、操作系统、浏览器)的不同,更改传播到所有上下文可能需要一段时间。为了同步,需要 atomic 操作。
¥Shared memory can be created and updated simultaneously in workers or the main thread. Depending on the system (the CPU, the OS, the Browser) it can take a while until the change is propagated to all contexts. To synchronize, atomic operations are needed.
SharedArrayBuffer 对象由某些 Web API 使用,例如:
¥SharedArrayBuffer objects are used by some web APIs, such as:
安全要求
¥Security requirements
鉴于 幽灵,共享内存和高分辨率定时器实际上是 2018 年初禁用。2020 年,一种新的安全方法已经标准化,可以重新启用共享内存。
¥Shared memory and high-resolution timers were effectively disabled at the start of 2018 in light of Spectre. In 2020, a new, secure approach has been standardized to re-enable shared memory.
作为基准要求,你的文档需要采用 安全上下文。
¥As a baseline requirement, your document needs to be in a secure context.
对于顶层文档,需要设置两个标头来跨源隔离你的站点:
¥For top-level documents, two headers need to be set to cross-origin isolate your site:
Cross-Origin-Opener-Policy和same-origin作为值(保护你的来源免受攻击者的攻击)Cross-Origin-Embedder-Policy与require-corp或credentialless作为值(保护受害者免受你的来源影响)
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
要检查跨源隔离是否成功,你可以针对窗口和工作上下文可用的 Window.crossOriginIsolated 属性或 WorkerGlobalScope.crossOriginIsolated 属性进行测试:
¥To check if cross origin isolation has been successful, you can test against the Window.crossOriginIsolated property or the WorkerGlobalScope.crossOriginIsolated property available to window and worker contexts:
const myWorker = new Worker("worker.js");
if (crossOriginIsolated) {
const buffer = new SharedArrayBuffer(16);
myWorker.postMessage(buffer);
} else {
const buffer = new ArrayBuffer(16);
myWorker.postMessage(buffer);
}
设置这两个标头后,postMessage() 不再抛出 SharedArrayBuffer 对象,因此跨线程的共享内存可用。
¥With these two headers set, postMessage() no longer throws for SharedArrayBuffer objects and shared memory across threads is therefore available.
嵌套文档和专用工作人员也需要设置 Cross-Origin-Embedder-Policy 标头,并具有相同的值。同源嵌套文档和子资源不需要进一步更改。同站点(但跨域)嵌套文档和子资源需要设置 Cross-Origin-Resource-Policy 标头并使用 same-site 作为值。而他们的跨域(和跨站点)对应者需要设置相同的标头,并将 cross-origin 作为值。请注意,将 Cross-Origin-Resource-Policy 标头设置为 same-origin 之外的任何其他值都会使资源遭受潜在攻击,例如 幽灵。
¥Nested documents and dedicated workers need to set the Cross-Origin-Embedder-Policy header as well, with the same value. No further changes are needed for same-origin nested documents and subresources. Same-site (but cross-origin) nested documents and subresources need to set the Cross-Origin-Resource-Policy header with same-site as value. And their cross-origin (and cross-site) counterparts need to set the same header with cross-origin as value. Note that setting the Cross-Origin-Resource-Policy header to any other value than same-origin opens up the resource to potential attacks, such as Spectre.
请注意,Cross-Origin-Opener-Policy 标头限制了你保留对弹出窗口的引用的能力。两个顶层窗口上下文之间的直接访问本质上只有在它们具有相同来源并且携带具有相同两个值的相同两个标头时才有效。
¥Note that the Cross-Origin-Opener-Policy header limits your ability to retain a reference to popups. Direct access between two top-level window contexts essentially only work if they are same-origin and carry the same two headers with the same two values.
API 可用性
¥API availability
根据是否采取上述安全措施,各种内存共享 API 具有不同的可用性:
¥Depending on whether the above security measures are taken, the various memory-sharing APIs have different availabilities:
Atomics对象始终可用。- 原则上,
SharedArrayBuffer对象始终可用,但不幸的是,除非设置了上述两个标头,否则全局对象的构造函数是隐藏的,以便与 Web 内容兼容。希望将来能够取消这一限制。WebAssembly.Memory仍然可以用来获取实例。 - 除非设置了上面提到的两个标头,否则各种
postMessage()API 将为SharedArrayBuffer对象抛出异常。如果设置了它们,Window对象上的postMessage()和专用工作线程将起作用并允许内存共享。
WebAssembly 共享内存
¥WebAssembly shared memory
可以使用 shared 构造函数标志创建 WebAssembly.Memory 对象。当此标志设置为 true 时,构造的 Memory 对象可以通过 postMessage() 在工作人员之间共享,就像 SharedArrayBuffer 一样,而 Memory 对象的支持 buffer 是 SharedArrayBuffer。因此,上面列出的在工人之间共享 SharedArrayBuffer 的要求也适用于共享 WebAssembly.Memory。
¥WebAssembly.Memory objects can be created with the shared constructor flag. When this flag is set to true, the constructed Memory object can be shared between workers via postMessage(), just like SharedArrayBuffer, and the backing buffer of the Memory object is a SharedArrayBuffer. Therefore, the requirements listed above for sharing a SharedArrayBuffer between workers also apply to sharing a WebAssembly.Memory.
WebAssembly Threads 提案还定义了一组新的 atomic 指令。正如 SharedArrayBuffer 及其方法被无条件启用(并且只有线程之间的共享在新标头上被门控)一样,WebAssembly 原子指令也被无条件允许。
¥The WebAssembly Threads proposal also defines a new set of atomic instructions. Just as SharedArrayBuffer and its methods are unconditionally enabled (and only sharing between threads is gated on the new headers), the WebAssembly atomic instructions are also unconditionally allowed.
增加 SharedArrayBuffer
¥Growing SharedArrayBuffers
通过在调用 SharedArrayBuffer() 构造函数时包含 maxByteLength 选项,可以使 SharedArrayBuffer 对象可增长。你可以通过分别访问 growable 和 maxByteLength 属性来查询 SharedArrayBuffer 是否可增长以及其最大大小是多少。你可以通过 grow() 调用为可增长的 SharedArrayBuffer 分配新的大小。新字节被初始化为 0。
¥SharedArrayBuffer objects can be made growable by including the maxByteLength option when calling the SharedArrayBuffer() constructor. You can query whether a SharedArrayBuffer is growable and what its maximum size is by accessing its growable and maxByteLength properties, respectively. You can assign a new size to a growable SharedArrayBuffer with a grow() call. New bytes are initialized to 0.
这些功能使 SharedArrayBuffer 的增长更加高效 - 否则,你必须使用新大小制作缓冲区的副本。在这方面,它还使 JavaScript 与 WebAssembly 同等(Wasm 线性内存可以使用 WebAssembly.Memory.prototype.grow() 调整大小)。
¥These features make growing SharedArrayBuffers more efficient — otherwise, you have to make a copy of the buffer with a new size. It also gives JavaScript parity with WebAssembly in this regard (Wasm linear memory can be resized with WebAssembly.Memory.prototype.grow()).
出于安全原因,SharedArrayBuffer 无法缩小尺寸,只能增大。
¥For security reasons, SharedArrayBuffers cannot be reduced in size, only grown.
构造函数
静态属性
实例属性
¥Instance properties
这些属性在 SharedArrayBuffer.prototype 上定义并由所有 SharedArrayBuffer 实例共享。
¥These properties are defined on SharedArrayBuffer.prototype and shared by all SharedArrayBuffer instances.
-
数组的大小(以字节为单位)。这是在构造数组时确定的,并且如果
SharedArrayBuffer可增长,则只能使用SharedArrayBuffer.prototype.grow()方法进行更改。 -
创建实例对象的构造函数。对于
SharedArrayBuffer实例,初始值为SharedArrayBuffer构造函数。 -
只读。如果
SharedArrayBuffer可以生长,则返回true;如果不能,则返回false。 -
SharedArrayBuffer可以增长到的只读最大长度(以字节为单位)。这是在构造数组时确定的并且无法更改。 -
[Symbol.toStringTag]属性的初始值为字符串"SharedArrayBuffer"。该属性在Object.prototype.toString()中使用。
实例方法
示例
创建一个新的 SharedArrayBuffer
对 SharedArrayBuffer 进行切片
在 WebGL 缓冲区中使用它
规范
| Specification |
|---|
| ECMAScript Language Specification # sec-sharedarraybuffer-objects |
浏览器兼容性
BCD tables only load in the browser
也可以看看
¥See also
AtomicsArrayBuffer- JavaScript 类型数组 指南
- Web 工作线程
- TC39 ecmascript-sharedmem 提案中的 共享内存 – 简短教程
- hacks.mozilla.org 上的 JavaScript 的新并行原语初体验 (2016)
- Chrome 团队的 COOP 和 COEP 解释 (2020)
Cross-Origin-Opener-PolicyCross-Origin-Embedder-PolicyCross-Origin-Resource-PolicyWindow.crossOriginIsolatedandWorkerGlobalScope.crossOriginIsolated- developer.chrome.com 上的 Android Chrome 88 和桌面版 Chrome 92 中的 SharedArrayBuffer 更新 (2021)