SharedArrayBuffer
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since December 2021.
Das SharedArrayBuffer
-Objekt wird verwendet, um einen generischen, rohen binären Datenpuffer darzustellen, ähnlich dem ArrayBuffer
-Objekt, jedoch so, dass sie zur Erstellung von Ansichten auf den geteilten Speicher genutzt werden können. Ein SharedArrayBuffer
ist kein transferierbares Objekt, im Gegensatz zu einem ArrayBuffer
, der transferierbar ist.
Beschreibung
Um Speicher mithilfe von SharedArrayBuffer
-Objekten von einem Agenten im Cluster zu einem anderen zu teilen (ein Agent ist entweder das Hauptprogramm der Webseite oder einer ihrer Web-Worker), wird postMessage
und das strukturierte Klonen verwendet.
Der Strukturierte Klon-Algorithmus akzeptiert SharedArrayBuffer
-Objekte und mit SharedArrayBuffer
-Objekten abgebildete typisierte Arrays. In beiden Fällen wird das SharedArrayBuffer
-Objekt zum Empfänger übertragen, was zu einem neuen, privaten SharedArrayBuffer
-Objekt im empfangenden Agenten führt (wie bei ArrayBuffer
). Jedoch ist der mit den beiden SharedArrayBuffer
-Objekten referenzierte gemeinsame Datenblock derselbe Datenblock, und eine Nebenwirkung auf den Block in einem Agenten wird schließlich im anderen Agenten sichtbar.
const sab = new SharedArrayBuffer(1024);
worker.postMessage(sab);
Geteilter Speicher kann gleichzeitig in Workern oder dem Haupt-Thread erstellt und aktualisiert werden. Je nach System (CPU, Betriebssystem, Browser) kann es eine Weile dauern, bis die Änderung in allen Kontexten propagiert wird. Zur Synchronisation sind atomare Operationen nötig.
SharedArrayBuffer
-Objekte werden von einigen Web-APIs verwendet, wie zum Beispiel:
Sicherheitsanforderungen
Geteilter Speicher und Hochauflösungs-Timer wurden Anfang 2018 effektiv deaktiviert im Hinblick auf Spectre. 2020 wurde ein neuer, sicherer Ansatz standardisiert, um geteilten Speicher wieder zu aktivieren.
Als grundlegende Anforderung muss Ihr Dokument in einem sicheren Kontext sein.
Für Top-Level-Dokumente müssen zwei Header gesetzt werden, um Ihre Website zu Cross-Origin-Isolieren:
Cross-Origin-Opener-Policy
mit dem Wertsame-origin
(schützt Ihren Ursprung vor Angreifern)Cross-Origin-Embedder-Policy
mit dem Wertrequire-corp
odercredentialless
(schützt Opfer vor Ihrem Ursprung)
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Um zu überprüfen, ob die Cross-Origin-Isolierung erfolgreich war, können Sie die Window.crossOriginIsolated
-Eigenschaft oder die WorkerGlobalScope.crossOriginIsolated
-Eigenschaft testen, die in Fenster- und Worker-Kontexten verfügbar ist:
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);
}
Mit diesen beiden gesetzten Headern wirft postMessage()
nicht länger für SharedArrayBuffer
-Objekte und damit ist geteilter Speicher über Threads hinweg verfügbar.
Eingebettete Dokumente und dedizierte Worker müssen ebenfalls den Cross-Origin-Embedder-Policy
-Header mit demselben Wert setzen. Keine weiteren Änderungen sind für gleichherkömmliche eingebettete Dokumente und Subressourcen nötig. Gleichseitige (aber Cross-Origin) eingebettete Dokumente und Subressourcen müssen den Cross-Origin-Resource-Policy
-Header mit dem Wert same-site
setzen. Und ihre Cross-Origin (und Cross-Site) Gegenstücke müssen denselben Header mit dem Wert cross-origin
setzen. Beachten Sie, dass das Setzen des Cross-Origin-Resource-Policy
-Headers auf einen anderen Wert als same-origin
die Ressource für potenzielle Angriffe wie Spectre öffnet.
Beachten Sie, dass der Cross-Origin-Opener-Policy
-Header Ihre Fähigkeit einschränkt, eine Referenz zu Popups zu behalten. Direkter Zugriff zwischen zwei Top-Level-Fenster-Kontexten funktioniert im Wesentlichen nur, wenn sie gleichherkömmlich sind und dieselben zwei Header mit denselben zwei Werten tragen.
API-Verfügbarkeit
Abhängig von den oben genannten Sicherheitsmaßnahmen haben die verschiedenen Speicherfreigabe-APIs unterschiedliche Verfügbarkeiten:
- Das
Atomics
-Objekt ist immer verfügbar. SharedArrayBuffer
-Objekte sind grundsätzlich immer verfügbar, aber leider ist der Konstruktor am globalen Objekt versteckt, es sei denn, die oben genannten zwei Header sind gesetzt, um die Kompatibilität mit Webinhalten zu gewährleisten. Es besteht Hoffnung, dass diese Einschränkung in der Zukunft entfernt werden kann.WebAssembly.Memory
kann immer noch verwendet werden, um eine Instanz zu erhalten.- Sofern die oben genannten zwei Header nicht gesetzt sind, werfen die verschiedenen
postMessage()
-APIs fürSharedArrayBuffer
-Objekte. Sind sie gesetzt, funktionierenpostMessage()
aufWindow
-Objekten und dedizierten Workern und erlauben das Teilen von Speicher.
WebAssembly-geteilter Speicher
WebAssembly.Memory
-Objekte können mit dem shared
-Konstruktor-Flag erstellt werden. Wenn dieses Flag auf true
gesetzt ist, kann das erstellte Memory
-Objekt zwischen Workern über postMessage()
geteilt werden, genau wie SharedArrayBuffer
, und der zugrunde liegende buffer
des Memory
-Objekts ist ein SharedArrayBuffer
. Daher gelten die oben aufgelisteten Anforderungen für das Teilen eines SharedArrayBuffer
zwischen Workern auch für das Teilen eines WebAssembly.Memory
.
Der WebAssembly Threads-Vorschlag definiert auch eine neue Reihe von atomaren Anweisungen. Genau wie SharedArrayBuffer
und seine Methoden unconditionally enabled sind (und nur das Teilen zwischen Threads auf die neuen Header beschränkt ist), sind die WebAssembly atomaren Anweisungen auch bedingungslos erlaubt.
Wachsende SharedArrayBuffers
SharedArrayBuffer
-Objekte können wachstumsfähig gemacht werden, indem die Option maxByteLength
beim Aufruf des SharedArrayBuffer()
-Konstruktors einbezogen wird. Sie können ermitteln, ob ein SharedArrayBuffer
wachstumsfähig ist und welches seine maximale Größe ist, indem Sie jeweils auf seine growable
- und maxByteLength
-Eigenschaften zugreifen. Sie können einem wachstumsfähigen SharedArrayBuffer
eine neue Größe zuweisen, indem Sie einen grow()
-Aufruf durchführen. Neue Bytes werden mit 0 initialisiert.
Diese Features machen das Wachsen von SharedArrayBuffer
s effizienter – ansonsten müssten Sie eine Kopie des Puffers mit einer neuen Größe anfertigen. Es gibt auch eine Parität mit WebAssembly in dieser Hinsicht (Wasm lineare Speicher kann mit WebAssembly.Memory.prototype.grow()
) verändert werden.
Aus Sicherheitsgründen können SharedArrayBuffer
s nicht verkleinert, sondern nur vergrößert werden.
Konstruktor
-
Erstellt ein neues
SharedArrayBuffer
-Objekt.
Statische Eigenschaften
-
Gibt den Konstruktor zurück, der verwendet wird, um Rückgabewerte von
SharedArrayBuffer
-Methoden zu konstruieren.
Instanzeigenschaften
Diese Eigenschaften sind auf SharedArrayBuffer.prototype
definiert und werden von allen SharedArrayBuffer
-Instanzen geteilt.
-
Die Größe in Bytes des Arrays. Diese wird bei der Konstruktion des Arrays festgelegt und kann nur mit der
SharedArrayBuffer.prototype.grow()
-Methode geändert werden, wenn derSharedArrayBuffer
wachstumsfähig ist. -
Die Konstruktionsfunktion, die das Instanz-Objekt erstellt hat. Für
SharedArrayBuffer
-Instanzen ist der Anfangswert derSharedArrayBuffer
-Konstruktor. -
Nur-Lese-Attribut. Gibt
true
zurück, wenn derSharedArrayBuffer
wachsen kann, oderfalse
, wenn nicht. -
Die maximal mögliche Länge in Bytes, auf die der
SharedArrayBuffer
wachsen kann. Diese wird bei der Konstruktion des Arrays festgelegt und kann nicht geändert werden. -
Der Anfangswert der
[Symbol.toStringTag]
-Eigenschaft ist der String"SharedArrayBuffer"
. Diese Eigenschaft wird inObject.prototype.toString()
verwendet.
Instanzmethoden
-
Vergrößert den
SharedArrayBuffer
auf die angegebene Größe in Bytes. -
Gibt einen neuen
SharedArrayBuffer
zurück, dessen Inhalt eine Kopie der Bytes diesesSharedArrayBuffer
vonbegin
, einschließlich bisend
, ausschließlich ist. Wennbegin
oderend
negativ ist, bezieht es sich auf einen Index vom Ende des Arrays, im Gegensatz zum Anfang.
Beispiele
Erstellen eines neuen SharedArrayBuffer
const sab = new SharedArrayBuffer(1024);
Slicing des SharedArrayBuffer
sab.slice(); // SharedArrayBuffer { byteLength: 1024 }
sab.slice(2); // SharedArrayBuffer { byteLength: 1022 }
sab.slice(-2); // SharedArrayBuffer { byteLength: 2 }
sab.slice(0, 1); // SharedArrayBuffer { byteLength: 1 }
Verwendung in einem WebGL-Puffer
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl");
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, sab, gl.STATIC_DRAW);
Spezifikationen
Specification |
---|
ECMAScript Language Specification # sec-sharedarraybuffer-objects |
Browser-Kompatibilität
BCD tables only load in the browser
Siehe auch
Atomics
ArrayBuffer
- JavaScript typisierte Arrays Leitfaden
- Web Worker
- Shared Memory – ein kurzes Tutorial im TC39 Ecmascript-Sharedmem-Vorschlag
- A Taste of JavaScript's New Parallel Primitives auf hacks.mozilla.org (2016)
- COOP und COEP erklärt vom Chrome-Team (2020)
Cross-Origin-Opener-Policy
Cross-Origin-Embedder-Policy
Cross-Origin-Resource-Policy
Window.crossOriginIsolated
undWorkerGlobalScope.crossOriginIsolated
- Updates zu SharedArrayBuffer in Android Chrome 88 und Desktop Chrome 92 auf developer.chrome.com (2021)