SharedArrayBuffer dalam JavaScript
Artikel ini menjelaskan SharedArrayBuffer
dalam JavaScript.
Kami akan memberikan penjelasan rinci tentang dasar-dasar SharedArrayBuffer
, cara menggunakannya, kasus penggunaan spesifik, dan pertimbangan keamanan.
YouTube Video
SharedArrayBuffer dalam JavaScript
SharedArrayBuffer
adalah alat yang kuat dalam JavaScript untuk berbagi memori antara beberapa thread. Terutama jika dikombinasikan dengan Web Workers, hal ini memungkinkan pemrosesan paralel, sehingga efektif untuk tugas intensif komputasi dan aplikasi yang memerlukan kemampuan real-time.
Apa itu SharedArrayBuffer?
SharedArrayBuffer
menyediakan buffer memori dalam JavaScript yang memungkinkan berbagi data biner antara beberapa thread (terutama Web Workers). ArrayBuffer
biasa memerlukan penyalinan antara thread utama dan worker, tetapi SharedArrayBuffer
memungkinkan berbagi memori secara langsung tanpa penyalinan, sehingga secara signifikan meningkatkan kinerja.
Fitur
- Memori Bersama Ini memungkinkan beberapa thread untuk bekerja dengan ruang memori yang sama.
- Peningkatan Performa Karena penyalinan dapat dihilangkan, overhead berkurang saat memproses data dalam jumlah besar.
- Sinkronisasi Thread
Anda dapat menggunakannya bersama dengan
Atomics
untuk melakukan sinkronisasi guna menghindari konflik saat mengakses memori.
Contoh Penggunaan Dasar
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, kita membuat area memori 16-byte menggunakan SharedArrayBuffer
dan memperlakukan area memori tersebut sebagai Int32Array
. Buffer memori ini dapat dibagi di antara beberapa thread.
Menggunakan dengan Web Workers
Nilai sebenarnya dari SharedArrayBuffer
ditunjukkan ketika digunakan bersama dengan Web Workers. Kode berikut adalah contoh penggunaan memori bersama antara thread utama dan worker.
Di Thread 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 Sisi Worker (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, thread utama membuat buffer bersama dan menyerahkannya ke worker. Worker dapat mengakses buffer ini untuk membaca dan memodifikasi nilai. Dengan cara ini, data dapat dibagi di antara thread tanpa penyalinan.
Konfirmasi Pembaruan Dua Arah
Dengan menggunakan SharedArrayBuffer
, baik thread utama maupun worker dapat membaca dan menulis ke memori yang sama, memungkinkan konfirmasi pembaruan dua arah. Di bawah ini adalah contoh di mana thread utama menetapkan sebuah nilai, worker mengubah nilai tersebut, lalu thread utama memeriksa pembaruan tersebut.
Di Thread 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 Sisi Worker (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, thread utama menulis nilai
100
terlebih dahulu, dan setelah worker membacanya, worker menulis ulang menjadi200
. Setelah itu, worker memberi tahu thread utama, dan thread utama membaca memori bersama lagi untuk mengonfirmasi pembaruan. Dengan cara ini, kombinasi notifikasi memungkinkan konfirmasi pembaruan dua arah.
Sinkronisasi dengan Atomics
Ketika menggunakan memori bersama, seseorang harus berhati-hati terhadap kondisi data race dan inkonsistensi. Ketika beberapa thread mengakses memori yang sama secara bersamaan, konflik dapat terjadi. Untuk mencegah ini, JavaScript menggunakan objek Atomics
untuk sinkronisasi.
Sebagai contoh, untuk meningkatkan penghitung dengan aman melalui beberapa thread, Anda dapat menggunakan Atomics
untuk mencegah 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 di indeks tertentu secara atomik dan mengembalikan nilai baru. Operasi ini dijamin bebas konflik dengan thread lainnya. Atomics.load
juga digunakan untuk membaca nilai dari memori bersama dengan aman.
Menunggu dan Notifikasi Menggunakan Atomics.wait
dan Atomics.notify
Saat menggunakan SharedArrayBuffer
, ada situasi di mana worker harus menunggu hingga kondisi tertentu terpenuhi, dan setelah worker lain memenuhi kondisi tersebut, worker tersebut harus memberi tahu worker yang sedang menunggu. Dalam kasus seperti itu, Atomics.wait
dan Atomics.notify
sangat berguna.
Atomics.wait
memblokir sebuah thread hingga nilai di indeks tertentu dalam memori bersama berubah, sedangkan Atomics.notify
memberi tahu thread yang sedang menunggu bahwa mereka dapat melanjutkan. Ini memungkinkan proses menunggu dan notifikasi yang aman di antara beberapa worker. Namun, Atomics.wait
tidak dapat digunakan di thread utama dan hanya tersedia di dalam 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};
- Di thread utama, sebuah
SharedArrayBuffer
dibuat sebagai memori bersama dan diubah menjadiInt32Array
dengan hanya satu elemen. Slot integer tunggal ini digunakan sebagai sinyal untuk melakukan sinkronisasi antara worker. Selanjutnya, dua worker dibuat, dan masing-masing diberikan peran menggunakan propertiname
:waiter
(sebagai penunggu) dannotifier
(sebagai pemberi notifikasi). Akhirnya, buffer yang dibagikan diteruskan ke kedua worker, dan handleronmessage
disiapkan agar pesan yang dikirim dari tiap worker dapat diterima.
Di Sisi Worker (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!
- Pada contoh ini, worker
waiter
tetap berada dalam keadaan menunggu menggunakanAtomics.wait
selama nilai pada indeks0
adalah0
. Di sisi lain, ketika workernotifier
mengubah nilainya menjadi123
denganAtomics.store
dan memanggilAtomics.notify
, workerwaiter
akan melanjutkan dan dapat mendapatkan nilai terbaru. Dengan cara ini, proses menunggu dan notifikasi antar thread yang efisien dan aman dapat dicapai.
Penggunaan Kasus untuk SharedArrayBuffer
SharedArrayBuffer
sangat berguna untuk penggunaan kasus berikut:.
- Pemrosesan Waktu Nyata Ini cocok untuk aplikasi yang memerlukan latensi rendah, seperti pemrosesan audio dan video atau engine game, di mana data perlu dibagikan secara instan antar thread.
- Komputasi Paralel
Saat memproses data dalam jumlah besar secara bersamaan dengan beberapa thread, penggunaan
SharedArrayBuffer
menghindari penyalinan memori dan dapat meningkatkan performa. - Pembelajaran Mesin Dengan memparalelkan tugas-tugas seperti praproses data dan inferensi, komputasi yang efisien menjadi mungkin.
Pertimbangan Keamanan
SharedArrayBuffer
adalah fitur yang kuat, tetapi juga membawa risiko keamanan. Terutama, kekhawatiran tentang serangan side-channel seperti Spectre
telah menghentikan dukungannya untuk sementara waktu. Untuk mengurangi kerentanan ini, browser telah mengimplementasikan langkah-langkah berikut:.
- Isolasi Situs
Situs yang mengizinkan penggunaan
SharedArrayBuffer
akan berjalan dalam proses yang sepenuhnya terisolasi dari situs lain. - Kebijakan Sumber Daya Cross-Origin
Untuk menggunakan
SharedArrayBuffer
, headerCross-Origin-Opener-Policy
danCross-Origin-Embedder-Policy
harus diatur dengan benar.
Sebagai contoh, dengan mengatur header seperti berikut, penggunaan SharedArrayBuffer
menjadi mungkin:.
1Cross-Origin-Opener-Policy: same-origin
2Cross-Origin-Embedder-Policy: require-corp
Ini mencegah sumber daya eksternal mengganggu konten saat ini dan meningkatkan keamanan.
Ringkasan
SharedArrayBuffer
adalah alat yang sangat kuat untuk berbagi memori antar beberapa thread. Ini adalah teknologi penting untuk meningkatkan kinerja, dan efeknya sangat terlihat terutama dalam bidang pemrosesan real-time dan komputasi paralel. Namun, ini juga melibatkan risiko keamanan, sehingga konfigurasi dan sinkronisasi yang benar sangat penting.
Dengan memanfaatkan SharedArrayBuffer
, Anda dapat membangun aplikasi web yang lebih canggih dan berkinerja tinggi.
Anda dapat mengikuti artikel di atas menggunakan Visual Studio Code di saluran YouTube kami. Silakan periksa juga saluran YouTube kami.