SharedArrayBuffer dalam JavaScript
Artikel ini menerangkan SharedArrayBuffer
dalam JavaScript.
Kami akan memberikan penjelasan terperinci mengenai asas SharedArrayBuffer
, cara penggunaannya, kes-kes penggunaan tertentu, dan pertimbangan keselamatan.
YouTube Video
SharedArrayBuffer dalam JavaScript
SharedArrayBuffer
adalah alat yang berkuasa dalam JavaScript untuk berkongsi memori antara pelbagai urutan. Terutamanya apabila digabungkan dengan Web Workers, ia membolehkan pemprosesan selari, menjadikannya berkesan untuk tugas berat pengiraan dan aplikasi yang memerlukan keupayaan masa nyata.
Apakah itu SharedArrayBuffer?
SharedArrayBuffer
menyediakan penampan memori dalam JavaScript yang membolehkan perkongsian data binari antara pelbagai urutan (terutamanya Web Workers). ArrayBuffer
biasa memerlukan salinan antara urutan utama dan pekerja, tetapi SharedArrayBuffer
membolehkan perkongsian memori terus tanpa salinan, sekali gus meningkatkan prestasi dengan ketara.
Ciri-ciri
- Memori Berkongsi Ia membolehkan berbilang benang bekerja dalam ruang memori yang sama.
- Penambahbaikan Prestasi Memandangkan penyalinan boleh diabaikan, lebihan proses dikurangkan apabila memproses sejumlah besar data.
- Penyegerakan Benang
Anda boleh menggunakannya bersama-sama dengan
Atomics
untuk melakukan penyegerakan bagi mengelakkan konflik semasa mengakses memori.
Contoh Penggunaan Asas
1// Create a 16-byte shared memory
2const sharedBuffer = new SharedArrayBuffer(16);
3
4// Treat it as an Int32Array
5const sharedArray = new Int32Array(sharedBuffer);
6
7// Set a value
8sharedArray[0] = 42;
9
10console.log(sharedArray[0]); // 42
Dalam contoh ini, kami mencipta kawasan memori 16-byte menggunakan SharedArrayBuffer
dan menganggap kawasan memori tersebut sebagai Int32Array
. Penampan memori ini boleh dikongsi di antara pelbagai urutan.
Menggunakan dengan Web Workers
Nilai sebenar SharedArrayBuffer
ditunjukkan apabila digunakan bersama-sama dengan Web Workers. Kod berikut adalah contoh penggunaan memori yang dikongsi antara urutan utama dan pekerja.
Pada Urutan Utama
1// Create a shared buffer
2const sharedBuffer = new SharedArrayBuffer(16);
3const sharedArray = new Int32Array(sharedBuffer);
4
5// Create a worker
6const worker = new Worker('worker.js');
7
8// Pass the shared buffer to the worker
9worker.postMessage(sharedBuffer);
10
11// Modify the memory
12// Output : Main thread: 100
13sharedArray[0] = 100;
14console.log("Main thread: ", sharedArray[0]);
Di Pihak Pekerja (worker.js
)
1// worker.js
2self.onmessage = function(event) {
3 // Use the received shared buffer
4 const sharedArray = new Int32Array(event.data);
5
6 // Read the contents of the memory
7 // Output : Worker thread: 100
8 console.log("Worker thread: ", sharedArray[0]);
9
10 // Change the value
11 sharedArray[0] = 200;
12};
- Dalam contoh ini, urutan utama mencipta penampan yang dikongsi dan menyerahkannya kepada pekerja. Pekerja boleh mengakses penampan ini untuk membaca dan mengubah nilai. Dengan cara ini, data boleh dikongsi antara urutan tanpa salinan.
Pengesahan Kemaskini Dua Hala
Dengan menggunakan SharedArrayBuffer
, kedua-dua benang utama dan pekerja boleh membaca dan menulis pada memori yang sama, membolehkan pengesahan kemaskini dua hala. Di bawah ialah contoh di mana benang utama menetapkan satu nilai, seorang pekerja mengubah nilai itu, dan kemudian benang utama menyemak kemaskini tersebut.
Pada Urutan Utama
1// Create a shared buffer
2const sharedBuffer = new SharedArrayBuffer(16);
3const sharedArray = new Int32Array(sharedBuffer);
4
5// Create a worker
6const worker = new Worker('worker.js');
7
8// Pass the shared buffer to the worker
9worker.postMessage(sharedBuffer);
10
11// Set initial value
12// Output : Main thread initial: 100
13sharedArray[0] = 100;
14console.log("Main thread initial:", sharedArray[0]);
15
16// Listen for worker confirmation
17worker.onmessage = () => {
18 // Output : Main thread after worker update: 200
19 console.log("Main thread after worker update:", sharedArray[0]);
20};
Di Pihak Pekerja (worker.js
)
1// worker.js
2self.onmessage = function(event) {
3 const sharedArray = new Int32Array(event.data);
4
5 // Read initial value
6 // Output : Worker thread received: 100
7 console.log("Worker thread received:", sharedArray[0]);
8
9 // Update the value
10 sharedArray[0] = 200;
11
12 // Notify main thread
13 self.postMessage("Value updated");
14};
- Dalam contoh ini, benang utama menulis nilai
100
terlebih dahulu, dan selepas pekerja membaca nilai tersebut, ia ditulis semula menjadi200
. Selepas itu, pekerja memaklumkan kepada benang utama, dan benang utama membaca memori berkongsi sekali lagi untuk mengesahkan kemaskini. Dengan cara ini, gabungan pemberitahuan membolehkan pengesahan kemaskini dua hala.
Penyelarasan dengan Atomics
Apabila menggunakan memori dikongsi, seseorang mesti berhati-hati terhadap keadaan perlumbaan data dan ketidakkonsistenan. Apabila beberapa utas mengakses memori yang sama secara serentak, konflik boleh berlaku. Untuk mengelakkan ini, JavaScript menggunakan objek Atomics
untuk penyelarasan.
Sebagai contoh, untuk meningkatkan penunjuk kiraan dengan selamat menggunakan pelbagai utas, anda boleh menggunakan Atomics
untuk mengelakkan konflik.
1const sharedBuffer = new SharedArrayBuffer(16);
2const sharedArray = new Int32Array(sharedBuffer);
3
4// Increment the counter
5Atomics.add(sharedArray, 0, 1);
6
7console.log(Atomics.load(sharedArray, 0)); // 1
Atomics.add
menambah nilai pada indeks tertentu secara atomik dan mengembalikan nilai baru. Operasi ini dijamin bebas konflik dengan utas-utas lain. Atomics.load
juga digunakan untuk membaca nilai dengan selamat daripada memori kongsi.
Menunggu dan Pemberitahuan Menggunakan Atomics.wait
dan Atomics.notify
Apabila menggunakan SharedArrayBuffer
, terdapat situasi di mana seorang pekerja perlu menunggu sehingga satu keadaan tertentu dicapai, dan selepas seorang lagi pekerja memenuhi keadaan tersebut, pekerja itu harus memaklumkan kepada pekerja yang sedang menunggu. Dalam kes seperti ini, Atomics.wait
dan Atomics.notify
adalah berguna.
Atomics.wait
akan menyekat sesuatu benang sehingga nilai pada indeks tertentu dalam memori berkongsi berubah, manakala Atomics.notify
memaklumkan benang yang menunggu bahawa mereka boleh meneruskan. Ini membolehkan proses menunggu dan pemberitahuan dengan selamat di antara beberapa pekerja. Walau bagaimanapun, Atomics.wait
tidak boleh digunakan pada utas utama dan hanya tersedia di dalam pekerja (worker).
1// Create a shared buffer (1 Int32 slot is enough for signaling)
2const sharedBuffer = new SharedArrayBuffer(4);
3const sharedArray = new Int32Array(sharedBuffer);
4
5// Create workers with names
6const waiter = new Worker('worker.js', { name: 'waiter' });
7const notifier = new Worker('worker.js', { name: 'notifier' });
8
9// Pass the shared buffer to both
10waiter.postMessage(sharedBuffer);
11notifier.postMessage(sharedBuffer);
12
13// Listen for messages
14waiter.onmessage = (event) => {
15 console.log(`[Main] Message from waiter:`, event.data);
16};
17notifier.onmessage = (event) => {
18 console.log(`[Main] Message from notifier:`, event.data);
19};
- Pada utas utama,
SharedArrayBuffer
dicipta sebagai memori kongsi dan ditukar menjadiInt32Array
dengan hanya satu elemen. Slot integer tunggal ini digunakan sebagai isyarat untuk menyegerakkan antara pekerja (worker). Seterusnya, dua pekerja (worker) dicipta, dan setiap satu diberikan peranan menggunakan sifatname
:waiter
(peranan menunggu) dannotifier
(peranan memberitahu). Akhir sekali, penimbal kongsi diberikan kepada kedua-dua pekerja, dan pengendalionmessage
disediakan supaya mesej yang dihantar daripada setiap pekerja dapat diterima.
Di Pihak Pekerja (worker.js
)
1// worker.js
2onmessage = (event) => {
3 const sharedArray = new Int32Array(event.data);
4
5 if (self.name === 'waiter') {
6 postMessage('Waiter is waiting...');
7 // Wait until notifier signals index 0
8 Atomics.wait(sharedArray, 0, 0);
9 postMessage('Waiter was notified!');
10 }
11
12 if (self.name === 'notifier') {
13 postMessage('Notifier is preparing...');
14 setTimeout(() => {
15 // Notify waiter after 2 seconds
16 Atomics.store(sharedArray, 0, 1);
17 Atomics.notify(sharedArray, 0, 1);
18 postMessage('Notifier has sent the signal!');
19 }, 2000);
20 }
21};
22// Output
23// [Main] Message from waiter: Waiter is waiting...
24// [Main] Message from notifier: Notifier is preparing...
25// [Main] Message from notifier: Notifier has sent the signal!
26// [Main] Message from waiter: Waiter was notified!
- Dalam contoh ini, pekerja
waiter
akan kekal dalam keadaan menunggu menggunakanAtomics.wait
selagi nilai pada indeks0
adalah0
. Sebaliknya, apabila pekerjanotifier
menukar nilai kepada123
denganAtomics.store
dan memanggilAtomics.notify
, pekerjawaiter
akan menyambung semula dan boleh mendapatkan nilai terkini. Dengan ini, penantian dan pemberitahuan antara utas yang cekap dan selamat dapat dicapai.
Kes Penggunaan untuk SharedArrayBuffer
SharedArrayBuffer
amat berguna untuk kes penggunaan berikut:.
- Pemprosesan Masa Nyata Ia sesuai untuk aplikasi yang memerlukan kependaman yang rendah, seperti pemprosesan audio dan video atau enjin permainan, di mana data perlu dikongsi serta-merta antara benang.
- Pengkomputeran Selari
Apabila memproses sejumlah besar data secara serentak dengan berbilang benang, penggunaan
SharedArrayBuffer
dapat mengelakkan penyalinan memori dan meningkatkan prestasi. - Pembelajaran Mesin Dengan menjalankan tugas-tugas seperti prapemprosesan data dan inferens secara selari, pengiraan menjadi lebih cekap.
Pertimbangan Keselamatan
SharedArrayBuffer
adalah ciri yang berkuasa, tetapi ia juga melibatkan risiko keselamatan. Secara khusus, kebimbangan mengenai serangan saluran sisi seperti Spectre
telah menghentikan sementara sokongannya. Untuk mengurangkan kerentanan ini, pelayar telah melaksanakan langkah-langkah berikut:.
- Pengasingan Laman
Laman yang membenarkan penggunaan
SharedArrayBuffer
akan berjalan dalam proses yang benar-benar terasing daripada laman lain. - Dasar Sumber Lintas Asal
Untuk menggunakan
SharedArrayBuffer
, pengepalaCross-Origin-Opener-Policy
danCross-Origin-Embedder-Policy
mesti disetkan dengan betul.
Sebagai contoh, dengan menetapkan pengepala seperti berikut, penggunaan SharedArrayBuffer
menjadi mungkin:.
1Cross-Origin-Opener-Policy: same-origin
2Cross-Origin-Embedder-Policy: require-corp
Ini menghalang sumber luar daripada mengganggu kandungan semasa dan meningkatkan keselamatan.
Ringkasan
SharedArrayBuffer
adalah alat yang sangat berkuasa untuk berkongsi memori antara pelbagai utas. Ia adalah teknologi penting untuk meningkatkan prestasi, dan kesannya amat ketara dalam bidang pemprosesan masa nyata dan pengkomputeran selari. Walau bagaimanapun, ia juga melibatkan risiko keselamatan, jadi konfigurasi dan penyelarasan yang betul adalah penting.
Dengan memanfaatkan SharedArrayBuffer
, anda boleh membina aplikasi web yang lebih maju dan berprestasi tinggi.
Anda boleh mengikuti artikel di atas menggunakan Visual Studio Code di saluran YouTube kami. Sila lihat juga saluran YouTube kami.