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.
Đối tượng SharedArrayBuffer được dùng để biểu diễn bộ đệm dữ liệu nhị phân thô chung, tương tự như đối tượng ArrayBuffer, nhưng theo cách có thể được dùng để tạo khung nhìn trên bộ nhớ dùng chung. SharedArrayBuffer không phải là đối tượng có thể chuyển giao, không giống như ArrayBuffer là có thể chuyển giao.
Mô tả
Để chia sẻ bộ nhớ sử dụng đối tượng SharedArrayBuffer từ một tác nhân trong cụm đến tác nhân khác (một tác nhân là chương trình chính của trang web hoặc một trong các web worker của nó), postMessage và sao chép có cấu trúc được sử dụng.
Thuật toán sao chép có cấu trúc chấp nhận đối tượng SharedArrayBuffer và mảng được gõ kiểu được ánh xạ lên đối tượng SharedArrayBuffer. Trong cả hai trường hợp, đối tượng SharedArrayBuffer được truyền đến bộ nhận tạo ra đối tượng SharedArrayBuffer riêng tư mới trong tác nhân nhận (giống như đối với ArrayBuffer). Tuy nhiên, khối dữ liệu dùng chung được tham chiếu bởi hai đối tượng SharedArrayBuffer là cùng một khối dữ liệu, và tác dụng phụ lên khối trong một tác nhân cuối cùng sẽ hiển thị trong tác nhân kia.
const sab = new SharedArrayBuffer(1024);
worker.postMessage(sab);
Bộ nhớ dùng chung có thể được tạo và cập nhật đồng thời trong các worker hoặc luồng chính. Tùy thuộc vào hệ thống (CPU, hệ điều hành, trình duyệt), có thể mất một lúc để thay đổi được lan truyền đến tất cả các ngữ cảnh. Để đồng bộ hóa, cần các thao tác nguyên tử.
Đối tượng SharedArrayBuffer được sử dụng bởi một số API web, chẳng hạn như:
Yêu cầu bảo mật
Bộ nhớ dùng chung và bộ đếm thời gian độ phân giải cao đã bị vô hiệu hóa vào đầu năm 2018 do lỗ hổng Spectre. Năm 2020, một cách tiếp cận mới, an toàn đã được chuẩn hóa để bật lại bộ nhớ dùng chung.
Để sử dụng bộ nhớ dùng chung, tài liệu của bạn phải ở trong ngữ cảnh an toàn và cách ly cross-origin. Bạn có thể sử dụng các thuộc tính Window.crossOriginIsolated và WorkerGlobalScope.crossOriginIsolated để kiểm tra xem tài liệu có được cách ly cross-origin hay không:
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);
}
Khi được cách ly cross-origin, postMessage() không còn ném lỗi với đối tượng SharedArrayBuffer, và do đó bộ nhớ dùng chung giữa các luồng có sẵn.
Tính khả dụng của API
Tùy thuộc vào việc các biện pháp bảo mật nêu trên được thực hiện hay không, các API chia sẻ bộ nhớ khác nhau có tính khả dụng khác nhau:
- Đối tượng
Atomicsluôn khả dụng. - Đối tượng
SharedArrayBuffervề nguyên tắc luôn khả dụng, nhưng thật không may, constructor trên đối tượng toàn cục bị ẩn, trừ khi hai header được đề cập ở trên được thiết lập, vì lý do tương thích với nội dung web. Có hy vọng rằng hạn chế này có thể được loại bỏ trong tương lai.WebAssembly.Memoryvẫn có thể được sử dụng để lấy instance. - Trừ khi hai header được đề cập ở trên được thiết lập, các API
postMessage()khác nhau sẽ ném lỗi với đối tượngSharedArrayBuffer. Nếu chúng được thiết lập,postMessage()trên đối tượngWindowvà các worker chuyên dụng sẽ hoạt động và cho phép chia sẻ bộ nhớ.
Bộ nhớ dùng chung WebAssembly
Đối tượng WebAssembly.Memory có thể được tạo với cờ constructor shared. Khi cờ này được đặt thành true, đối tượng Memory được xây dựng có thể được chia sẻ giữa các worker thông qua postMessage(), giống như SharedArrayBuffer, và buffer của đối tượng Memory là SharedArrayBuffer. Do đó, các yêu cầu được liệt kê ở trên để chia sẻ SharedArrayBuffer giữa các worker cũng áp dụng để chia sẻ WebAssembly.Memory.
Đề xuất Luồng WebAssembly cũng định nghĩa một tập hợp mới các lệnh atomic. Giống như SharedArrayBuffer và các phương thức của nó được bật vô điều kiện (và chỉ việc chia sẻ giữa các luồng bị kiểm soát bởi các header mới), các lệnh atomic WebAssembly cũng được phép vô điều kiện.
Tăng trưởng SharedArrayBuffer
Đối tượng SharedArrayBuffer có thể được làm cho có thể tăng trưởng bằng cách bao gồm tùy chọn maxByteLength khi gọi constructor SharedArrayBuffer(). Bạn có thể truy vấn xem SharedArrayBuffer có thể tăng trưởng và kích thước tối đa của nó là bao nhiêu bằng cách truy cập các thuộc tính growable và maxByteLength tương ứng. Bạn có thể gán kích thước mới cho SharedArrayBuffer có thể tăng trưởng bằng lệnh gọi grow(). Các byte mới được khởi tạo bằng 0.
Các tính năng này làm cho việc tăng trưởng SharedArrayBuffer hiệu quả hơn — nếu không, bạn phải tạo bản sao của bộ đệm với kích thước mới. Nó cũng cung cấp cho JavaScript tính tương đương với WebAssembly trong vấn đề này (bộ nhớ tuyến tính Wasm có thể được thay đổi kích thước với WebAssembly.Memory.prototype.grow()).
Vì lý do bảo mật, SharedArrayBuffer không thể giảm kích thước, chỉ có thể tăng.
Constructor
-
Tạo đối tượng
SharedArrayBuffermới.
Thuộc tính tĩnh
-
Trả về constructor được sử dụng để xây dựng các giá trị trả về từ các phương thức
SharedArrayBuffer.
Thuộc tính instance
Các thuộc tính này được định nghĩa trên SharedArrayBuffer.prototype và được chia sẻ bởi tất cả các instance SharedArrayBuffer.
-
Kích thước, tính bằng byte, của mảng. Được thiết lập khi mảng được xây dựng và chỉ có thể thay đổi bằng phương thức
SharedArrayBuffer.prototype.grow()nếuSharedArrayBuffercó thể tăng trưởng. -
Hàm constructor đã tạo đối tượng instance. Đối với các instance
SharedArrayBuffer, giá trị khởi tạo là constructorSharedArrayBuffer. -
Chỉ đọc. Trả về
truenếuSharedArrayBuffercó thể tăng trưởng, hoặcfalsenếu không thể. -
Độ dài tối đa chỉ đọc, tính bằng byte, mà
SharedArrayBuffercó thể tăng trưởng đến. Được thiết lập khi mảng được xây dựng và không thể thay đổi. -
Giá trị khởi tạo của thuộc tính
[Symbol.toStringTag]là chuỗi"SharedArrayBuffer". Thuộc tính này được dùng trongObject.prototype.toString().
Phương thức instance
-
Tăng trưởng
SharedArrayBufferđến kích thước được chỉ định, tính bằng byte. -
Trả về
SharedArrayBuffermới có nội dung là bản sao các byte củaSharedArrayBuffernày từbegin(bao gồm) đếnend(không bao gồm). Nếubeginhoặcendâm, nó tham chiếu đến chỉ số tính từ cuối mảng, thay vì từ đầu.
Ví dụ
Lưu ý rằng các ví dụ này không thể chạy trực tiếp từ console hoặc trang web tùy ý, vì SharedArrayBuffer không được định nghĩa trừ khi yêu cầu bảo mật của nó được đáp ứng.
Tạo SharedArrayBuffer mới
const sab = new SharedArrayBuffer(1024);
Cắt 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 }
Sử dụng trong bộ đệm WebGL
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);
Đặc tả kỹ thuật
| Specification |
|---|
| ECMAScript® 2027 Language Specification> # sec-sharedarraybuffer-objects> |
Tương thích trình duyệt
Xem thêm
AtomicsArrayBuffer- Hướng dẫn JavaScript typed arrays
- Web Workers
- Shared Memory – a brief tutorial trong đề xuất TC39 ecmascript-sharedmem
- A Taste of JavaScript's New Parallel Primitives trên hacks.mozilla.org (2016)
- COOP and COEP explained bởi nhóm Chrome (2020)
Cross-Origin-Opener-PolicyCross-Origin-Embedder-PolicyCross-Origin-Resource-PolicyWindow.crossOriginIsolatedvàWorkerGlobalScope.crossOriginIsolated- SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome 92 trên developer.chrome.com (2021)