问题描述
所以,我正在阅读一些关于 Node.js 的东西,当我遇到 Worker Threads 时,我感到很惊讶.
So, I was reading some stuff regarding Node.js and I was amazed when I came across Worker Threads.
在我看来,拥有线程是一个很好的加分项,尤其是当您将其与共享内存访问结合使用时.正如您可能已经想到的那样->SharedArrayBuffer
...
Having threads in my opinion is a great plus especially if you combine it with shared memory access. As you might think already -> SharedArrayBuffer
...
是的,我就是这么想的.所以我想到的第一件事就是给它一个小测试,并尝试实现一个简单的 store
(现在是一个简单的对象),它将在线程之间共享.
Yeap that's what I thought. So The first thing that came into my mind was to give it a little test and try to implement a simple store
(a simple object for now) that would be shared among the threads.
问题是,(除非我在这里遗漏了一些东西)如何使用 SharedArrayBuffer
使对象可从 n 个线程访问?
The question is, (unless I'm missing something here) how can you make an object accessible from n threads with the use of SharedArrayBuffer
?
我知道对于一个简单的 Uint32Array
是可行的,但是关于对象可以做什么?
I know that for a simple Uint32Array
is doable, but regarding the object what can be done?
一开始我想把它转换成一个 Uint32Array
,你可能会在下面看到,但即使看到该死的源代码也让我想哭......
At first I thought to convert it to a Uint32Array
as you may see bellow, but even looking at the damn source code makes me wanna cry...
const {
Worker,
isMainThread,
workerData
} = require('worker_threads');
const store = {
ks109: {
title: 'some title 1',
description: 'some desciption 1',
keywords: ['one', 'two']
},
ks110: {
title: 'some title 2',
description: 'some desciption 2',
keywords: ['three', 'four']
},
ks111: {
title: 'some title 3',
description: 'some desciption 3',
keywords: ['five', 'six']
}
}
const shareObject = (obj) => {
let OString = JSON.stringify(obj);
let SABuffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * OString.length);
let sArray = new Int32Array(SABuffer);
for (let i = 0; i < OString.length; i++) {
sArray[i] = OString.charCodeAt(i);
}
return sArray;
}
if (isMainThread) {
const sharedStore = shareObject(store);
console.log('[Main][Data Before]:', sharedStore.slice(-10));
let w = new Worker(__filename, {
workerData: sharedStore
});
w.on('message', (msg) => {
console.log(`[Main][Thread message]: ${msg}`);
});
w.on('error', (err) => {
console.error(`[Main][Thread error] ${err.message}`);
});
w.on('exit', (code) => {
if (code !== 0) {
console.error(`[Main][Thread unexpected exit]: ${code}`);
}
});
setInterval(() => {
// At some point you ll see a value change,
// it's 'six' becoming 'sax' (big time!)
console.log('[Main][Data Check]:', sharedStore.slice(-10));
}, 1000);
} else {
let str = String.fromCharCode.apply(this, workerData);
let obj = JSON.parse(str);
obj.ks111.keywords[1] = 'sax'; // big time!
let OString = JSON.stringify(obj);
for (let i = 0; i < OString.length; i++) {
workerData[i] = OString.charCodeAt(i);
}
}
总之,Node.js 10.5.0 中的线程间共享对象,有可能吗?怎么样?
In conclusion, shared object among threads in Node.js 10.5.0, is it possible? How?
推荐答案
ECMA 脚本不包含共享对象,但它有 SharedArrayBuffer
.您可以使用 DataView
和包装器在自己的缓冲区中直接写入数据来实现此类行为:
ECMA Script contains no shared objects but it have SharedArrayBuffer
. And you can implement such behavior on your own writing data directly in buffer using DataView
and wrapper:
// Shared value
class SharedPoint {
constructor(array) {
this.dataview = new DataView(array);
}
set x(value) {
this.dataview.setUint8(0, value);
}
set y(value) {
this.dataview.setUint8(1, value);
}
get x() {
return this.dataview.getUint8(0);
}
get y() {
return this.dataview.getUint8(1);
}
}
// Usage
const buffer = new SharedArrayBuffer(2);
// Create two instances of shared point.
const point0 = new SharedPoint(buffer);
const point1 = new SharedPoint(buffer);
// Get initial values for point #1
console.log('x', point1.x); // 0
console.log('y', point1.y); // 0
// Update point #0
point0.x = 64;
point0.y = 32;
// Get changes in point #1
console.log('x', point1.x); // 64
console.log('y', point1.y); // 32
您可以创建可以操作字符串或 C 类结构的类一>.虽然 SharedArrayBuffer
是可传输对象,但它可以在工作进程和主进程之间共享.
You are able to create class which can manipulate strings or C-like structures. While SharedArrayBuffer
is tranferable object it can be shared between worker and main process.
⚠️ 注意 由于 Spectre 攻击 SharedArrayBuffer
是已被所有主要浏览器禁用,并在 Chrome 68 版和 Firefox 79 版后重新启用.检查浏览器支持 我可以使用.
这篇关于Node.js 工作线程共享对象/存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!