网络工作者的多线程是无效的吗?
Is multithreading with webworkers ineffective?
我有一个项目,我必须在其中处理相当大的对象,每个对象大约需要 500 毫秒。我认为使用 web workers 会大大加快这个过程。但是在使用 web worker 之后,他们似乎根本没有提高速度——即使我取消了创建 web worker 的预处理。
所以我决定创建一个简单的示例:有一个包含 N
个数字的数组,应该计算这些数字的总和。
首先,没有 webworkers (DEMO):
/** Goal: return sum of all numbers in array */
var numbers = [];
for(var i = 0; i < N; i++){
numbers.push(Math.floor(Math.random() * 100));
}
/** Test without web workers */
var total = 0;
for(var i = 0; i < numbers.length; i++){
total += numbers[i];
}
然后,与 网络工作者 (DEMO):
/** Options */
var WORKERS = 5; // N should be divisble by WORKERS
/** Test WITH web workers */
var workers = [];
var source = `
onmessage = function(e) {
var total = 0;
for(var i = 0; i < e.data.length; i++){
total += e.data[i];
}
postMessage(total);
}`
for(var i = 0; i < WORKERS; i++){
var blob = new Blob([source]);
var blobURL = window.URL.createObjectURL(blob);
let worker = new Worker(blobURL);
worker.onmessage = function(e){
total += e.data;
worker.terminate();
if(++finished == workers.length) done();
}
workers.push(worker);
}
var finished = 0;
var chunk = Math.floor(N / WORKERS);
var sliced = [];
for(var i = 0; i < workers.length; i++){
sliced.push(numbers.slice(i*chunk,i*chunk+chunk));
}
// we calculate time after we created the workers, from here
var total = 0;
for(var i = 0; i < workers.length; i++){
workers[i].postMessage(sliced[i]);
}
function done(){
// do something
}
所以结果:网络工作者似乎完全是灾难性的。它比没有网络工作者慢 10 倍以上。
所以我的问题是,谁能告诉我一个例子,其中使用 webworker 的多线程实际上更快?除了 运行 之外,我没能在不影响 UI 的情况下看到网络工作者的意义......
编辑: 它运行速度较慢,但 CPU 使用率更高(100% 有网络工作者,~30% 没有网络工作者)——这让我产生疑问所有的力量都将流向哪里
编辑 2: 即使您将 onmessage
留在 worker 端什么也不做,它仍然运行得更慢......似乎主线程和工作线程非常慢 (see for yourself)
编辑 3: 它与 postMessage
无关,我已经测量了性能,但我无法通过不同的编码来解决这个问题。最奇怪的是:当我使用 Google chrome 开发工具测量性能时,它的运行速度几乎是
的两倍
有趣article:
您的基准被向每个工人传输一千万个数字的成本淹没了。
相反,创建一个 ArrayBuffer
。将其作为 transferList
的一部分(postMessage
的第二个参数)传递。在我的机器上,工作人员 运行 完成这项工作不到 100 毫秒,而没有工作人员则需要 200 毫秒。
我有一个项目,我必须在其中处理相当大的对象,每个对象大约需要 500 毫秒。我认为使用 web workers 会大大加快这个过程。但是在使用 web worker 之后,他们似乎根本没有提高速度——即使我取消了创建 web worker 的预处理。
所以我决定创建一个简单的示例:有一个包含 N
个数字的数组,应该计算这些数字的总和。
首先,没有 webworkers (DEMO):
/** Goal: return sum of all numbers in array */
var numbers = [];
for(var i = 0; i < N; i++){
numbers.push(Math.floor(Math.random() * 100));
}
/** Test without web workers */
var total = 0;
for(var i = 0; i < numbers.length; i++){
total += numbers[i];
}
然后,与 网络工作者 (DEMO):
/** Options */
var WORKERS = 5; // N should be divisble by WORKERS
/** Test WITH web workers */
var workers = [];
var source = `
onmessage = function(e) {
var total = 0;
for(var i = 0; i < e.data.length; i++){
total += e.data[i];
}
postMessage(total);
}`
for(var i = 0; i < WORKERS; i++){
var blob = new Blob([source]);
var blobURL = window.URL.createObjectURL(blob);
let worker = new Worker(blobURL);
worker.onmessage = function(e){
total += e.data;
worker.terminate();
if(++finished == workers.length) done();
}
workers.push(worker);
}
var finished = 0;
var chunk = Math.floor(N / WORKERS);
var sliced = [];
for(var i = 0; i < workers.length; i++){
sliced.push(numbers.slice(i*chunk,i*chunk+chunk));
}
// we calculate time after we created the workers, from here
var total = 0;
for(var i = 0; i < workers.length; i++){
workers[i].postMessage(sliced[i]);
}
function done(){
// do something
}
所以结果:网络工作者似乎完全是灾难性的。它比没有网络工作者慢 10 倍以上。
所以我的问题是,谁能告诉我一个例子,其中使用 webworker 的多线程实际上更快?除了 运行 之外,我没能在不影响 UI 的情况下看到网络工作者的意义......
编辑: 它运行速度较慢,但 CPU 使用率更高(100% 有网络工作者,~30% 没有网络工作者)——这让我产生疑问所有的力量都将流向哪里
编辑 2: 即使您将 onmessage
留在 worker 端什么也不做,它仍然运行得更慢......似乎主线程和工作线程非常慢 (see for yourself)
编辑 3: 它与 postMessage
无关,我已经测量了性能,但我无法通过不同的编码来解决这个问题。最奇怪的是:当我使用 Google chrome 开发工具测量性能时,它的运行速度几乎是
有趣article:
您的基准被向每个工人传输一千万个数字的成本淹没了。
相反,创建一个 ArrayBuffer
。将其作为 transferList
的一部分(postMessage
的第二个参数)传递。在我的机器上,工作人员 运行 完成这项工作不到 100 毫秒,而没有工作人员则需要 200 毫秒。