什么是 Shared Memory?
Shared Memory 是一种多进程间共享内存的机制。在 JavaScript 中,由于每个 Tab 或者每个 Worker 都有自己独立的 VM 实例,所以数据是不能直接共享的。
在 Web Worker 中,需要使用 postMessage()
API 发送消息来传递数据。但当传递大量数据的时候,因为需要进行数据拷贝,会带来较大的性能损失。
ES8 引入的 Share Array Buffer 和 Atomics 可以让我们在多个 Worker 中共享内存,避免了数据拷贝,从而提高了性能。
Share Array Buffer
Share Array Buffer 是一种新的内存类型,在 JavaScript 引擎中分配连续内存块,可以存放不同类型的数据,如数字、字符串、对象、数组等。这些数据可以通过访问同一个内存地址来实现共享。
// 创建 Shared Array Buffer const sab = new SharedArrayBuffer(8); // 获取 ArrayBufferView const view = new Int32Array(sab); // 设置值 view[0] = 42; // 在 Worker 中使用共享的 ArrayBufferView worker.postMessage({view: view}, [view.buffer]);
在上述代码中,首先创建了一个大小为 8 字节的 ArrayBuffer,然后通过 Int32Array 获取了对应的 ArrayBufferView。接着,通过设置 view ArrayBufferView
中的值,将其传递到了一个 worker
中。
注意,当我们向 postMessage()
传递共享的 ArrayBufferView
时,我们需要将它转化为普通 ArrayBuffer,并以第二个参数的形式传递,这样就能让 worker 中得到这份内存的访问权。
Atomics
在多个 Worker 中共享同一个内存块,可能会产生协调和同步的问题。Atomics 负责解决这个问题。
Atomics 是一组可以原子性地操作共享内存的 API,支持原子操作的类型包括:整数(int32)、浮点数(float32、float64)和 64 位整数(Int64)。
const shmem = new SharedArrayBuffer(4); const arr = new Int32Array(shmem); // lock Atomics.wait(arr, 0, 0); // update value arr[0]++; // unlock Atomics.notify(arr, 0, 1);
上述代码中,我们首先创建了一个长度为 4 的 ArrayBuffer,然后使用 Int32Array 获取了对应的 ArrayBufferView,最终使用了 Atomics API 执行了原子操作。
在 Atomics 中,wait()
用于获取锁,notify()
用于释放锁。wait()
的第一个参数是一个共享内存的 ArrayBufferView,第二个参数是要访问内存的索引位置,第三个参数是锁的值。如果锁的值不匹配,那么当前线程会被阻塞,直到锁被释放。notify()
的第二个参数是访问内存的索引位置,第三个参数是要释放的锁的数量。
总结
ES8 引入了 Shared Memory 这个新的特性,可以让我们在多个 Worker 中共享内存,避免了数据拷贝,从而提高了性能。在使用时,需要注意协调和同步的问题,这可以通过 Atomics API 来解决。
在实际应用中,我们可以使用 Shared Memory 来优化一些计算密集型的任务,例如视频编解码、图像处理等等。同时,共享内存也能够节省内存空间,避免不必要的资源浪费。
参考文献
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6594cbe6eb4cecbf2d90fc66