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 SharedArrayBuffer
s 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, SharedArrayBuffer
s 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
Atomics
ArrayBuffer
- JavaScript 类型数组 指南
- Web 工作线程
- TC39 ecmascript-sharedmem 提案中的 共享内存 – 简短教程
- hacks.mozilla.org 上的 JavaScript 的新并行原语初体验 (2016)
- Chrome 团队的 COOP 和 COEP 解释 (2020)
Cross-Origin-Opener-Policy
Cross-Origin-Embedder-Policy
Cross-Origin-Resource-Policy
Window.crossOriginIsolated
andWorkerGlobalScope.crossOriginIsolated
- developer.chrome.com 上的 Android Chrome 88 和桌面版 Chrome 92 中的 SharedArrayBuffer 更新 (2021)