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.

* Some parts of this feature may have varying levels of support.

Das SharedArrayBuffer-Objekt wird verwendet, um einen generischen, rohen Binärdatenpuffer darzustellen, ähnlich dem ArrayBuffer-Objekt. Der Unterschied liegt darin, dass es ermöglicht, Ansichten auf gemeinsamen Speicher zu erstellen. Ein SharedArrayBuffer ist kein übertragbares Objekt im Gegensatz zu einem ArrayBuffer, das übertragbar ist.

Beschreibung

Um Speicher zwischen einem Agenten im Cluster und einem anderen zu teilen (ein Agent ist entweder das Hauptprogramm der Webseite oder einer ihrer Web-Worker), werden postMessage und strukturiertes Klonen verwendet.

Der Algorithmus zum strukturierten Klonen akzeptiert SharedArrayBuffer-Objekte und getypte Arrays, die auf SharedArrayBuffer-Objekte abgebildet sind. In beiden Fällen wird das SharedArrayBuffer-Objekt an den Empfänger übertragen, was in einem neuen, privaten SharedArrayBuffer-Objekt im empfangenden Agenten resultiert (ähnlich wie bei ArrayBuffer). Allerdings bezieht sich der gemeinsame Datenblock, auf den die beiden SharedArrayBuffer-Objekte verweisen, auf denselben Datenblock, und eine Nebenwirkung auf den Block in einem Agent wird schließlich im anderen Agent sichtbar.

js
const sab = new SharedArrayBuffer(1024);
worker.postMessage(sab);

Gemeinsamer Speicher kann gleichzeitig in Workern oder im Haupt-Thread erstellt und aktualisiert werden. Abhängig vom System (der CPU, dem Betriebssystem, dem Browser) kann es eine Weile dauern, bis die Änderung in allen Kontexten sichtbar wird. Zur Synchronisation sind Atomics-Operationen erforderlich.

SharedArrayBuffer-Objekte werden von einigen Web-APIs verwendet, wie zum Beispiel:

Sicherheitsanforderungen

Gemeinsamer Speicher und hochauflösende Timer wurden Anfang 2018 effektiv deaktiviert im Hinblick auf Spectre. Im Jahr 2020 wurde ein neuer, sicherer Ansatz standardisiert, um gemeinsamen Speicher wieder zu aktivieren.

Um gemeinsamen Speicher zu nutzen, muss Ihr Dokument in einem sicheren Kontext und cross-origin isoliert sein. Sie können die Eigenschaften Window.crossOriginIsolated und WorkerGlobalScope.crossOriginIsolated verwenden, um zu überprüfen, ob das Dokument cross-origin isoliert ist:

js
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);
}

Wenn cross-origin isoliert, wirft postMessage() nicht mehr für SharedArrayBuffer-Objekte, und gemeinsamer Speicher über Threads ist daher verfügbar.

Verfügbarkeit der API

Je nachdem, ob die oben genannten Sicherheitsmaßnahmen getroffen werden, sind die verschiedenen Speicherfreigabe-APIs unterschiedlich verfügbar:

  • Das Atomics-Objekt ist immer verfügbar.
  • SharedArrayBuffer-Objekte sind grundsätzlich immer verfügbar, aber leider ist der Konstruktor im globalen Objekt verborgen, es sei denn, die beiden oben genannten Header sind gesetzt, um die Kompatibilität mit Webinhalten zu gewährleisten. Es besteht die Hoffnung, dass diese Einschränkung in Zukunft aufgehoben werden kann. WebAssembly.Memory kann weiterhin verwendet werden, um eine Instanz zu erhalten.
  • Sofern die beiden oben genannten Header nicht gesetzt sind, werfen die verschiedenen postMessage()-APIs bei SharedArrayBuffer-Objekten. Wenn sie gesetzt sind, funktionieren postMessage() auf Window-Objekten und dedizierten Workern und ermöglichen das Teilen von Speicher.

Gemeinsamer WebAssembly-Speicher

WebAssembly.Memory-Objekte können mit dem shared-Konstruktor-Flag erstellt werden. Wenn dieses Flag auf true gesetzt ist, kann das konstruierte 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 aufgeführten Anforderungen für das Teilen eines SharedArrayBuffer zwischen Workern auch für das Teilen eines WebAssembly.Memory.

Der WebAssembly Threads Vorschlag definiert auch einen neuen Satz von atomaren Anweisungen. Genau wie SharedArrayBuffer und seine Methoden bedingungslos aktiviert sind (und nur das Teilen zwischen Threads durch die neuen Header gesteuert wird), sind die WebAssembly-atomaren Anweisungen ebenfalls ohne Bedingungen erlaubt.

Wachstum von SharedArrayBuffers

SharedArrayBuffer-Objekte können durch Einbeziehung der maxByteLength-Option beim Aufruf des SharedArrayBuffer()-Konstruktors wachstumsfähig gemacht werden. Sie können abfragen, ob ein SharedArrayBuffer wachstumsfähig ist und wie groß seine maximale Größe ist, indem Sie auf seine growable- und maxByteLength-Eigenschaften zugreifen. Sie können einem wachstumsfähigen SharedArrayBuffer eine neue Größe zuweisen, indem Sie einen grow()-Aufruf machen. Neue Bytes werden auf 0 initialisiert.

Diese Funktionen machen das Wachstum von SharedArrayBuffers effizienter – andernfalls müssten Sie eine Kopie des Buffers mit einer neuen Größe erstellen. Sie geben JavaScript auch Parität mit WebAssembly in dieser Hinsicht (Wasm-Linearspeicher kann mit WebAssembly.Memory.prototype.grow() neugestaltet werden).

Aus Sicherheitsgründen können SharedArrayBuffers nicht verkleinert, sondern nur vergrößert werden.

Konstruktor

SharedArrayBuffer()

Erstellt ein neues SharedArrayBuffer-Objekt.

Statische Eigenschaften

SharedArrayBuffer[Symbol.species]

Gibt den Konstruktor zurück, der verwendet wird, um Rückgabewerte von SharedArrayBuffer-Methoden zu konstruieren.

Instanz-Eigenschaften

Diese Eigenschaften sind auf SharedArrayBuffer.prototype definiert und werden von allen SharedArrayBuffer Instanzen geteilt.

SharedArrayBuffer.prototype.byteLength

Die Größe, in Bytes, des Arrays. Diese wird festgelegt, wenn das Array konstruiert wird und kann nur geändert werden, indem die SharedArrayBuffer.prototype.grow()-Methode aufgerufen wird, wenn das SharedArrayBuffer wachstumsfähig ist.

SharedArrayBuffer.prototype.constructor

Die Konstruktorfunktion, die das Instanz-Objekt erstellt hat. Für SharedArrayBuffer-Instanzen ist der Anfangswert der SharedArrayBuffer-Konstruktor.

SharedArrayBuffer.prototype.growable

Schreibtgeschützt. Gibt true zurück, wenn das SharedArrayBuffer vergrößert werden kann, oder false, wenn nicht.

SharedArrayBuffer.prototype.maxByteLength

Die schreibgeschützte maximale Länge, in Bytes, auf die das SharedArrayBuffer vergrößert werden kann. Diese wird beim Konstruieren des Arrays festgelegt und kann nicht geändert werden.

SharedArrayBuffer.prototype[Symbol.toStringTag]

Der Anfangswert der [Symbol.toStringTag]-Eigenschaft ist der String "SharedArrayBuffer". Diese Eigenschaft wird in Object.prototype.toString() verwendet.

Instanzmethoden

SharedArrayBuffer.prototype.grow()

Vergrößert das SharedArrayBuffer auf die angegebene Größe, in Bytes.

SharedArrayBuffer.prototype.slice()

Gibt ein neues SharedArrayBuffer zurück, dessen Inhalt eine Kopie der Bytes dieses SharedArrayBuffer von begin, inklusive, bis end, exklusiv ist. Wenn entweder begin oder end negativ sind, bezieht es sich auf einen Index vom Ende des Arrays, anstatt von Anfang.

Beispiele

Erstellen eines neuen SharedArrayBuffer

js
const sab = new SharedArrayBuffer(1024);

Ausschneiden des SharedArrayBuffer

js
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

js
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® 2025 Language Specification
# sec-sharedarraybuffer-objects

Browser-Kompatibilität

BCD tables only load in the browser

Siehe auch