网络工作者的多线程是无效的吗?

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 毫秒。

https://jsfiddle.net/ooduhb5h/7/