Home > Software engineering >  Javascript Worker Performance without onMessage
Javascript Worker Performance without onMessage

Time:07-25

I have observed an odd behavior of web workers. Assume worker.js to containt the code below

onmessage = 
function(event) 
{
 var x = event.data;
 var c = 0;
 
 for(var i = 0; i < x; i  ) c = c   Math.random();
 
 postMessage(c);
}

I create and worker, post "100000000" to it, to run it for 100 millions loops. It takes around 900 milliseconds.

Now, consider the same code, without an onmessage event. It will run right away after being created, without having to trigger it through postMessage.

 var x = 100000000;
 var c = 0;
 
 for(var i = 0; i < x; i  ) c = c   Math.random();
 
 postMessage(c);

Same 100 millions loops, but this this time it takes on average 2200 milliseconds. More than double.

Is there any explanation for this performance gap? A compilation issue perhaps?

Update, as requested, this is how performance is measured:

var worker = new Worker('worker.js');
var time   = performance.now();
worker.onmessage =
function(event)
{ 
 time = performance.now() - time;
}

CodePudding user response:

It seems that the main script isn't able to be detected as "hot" by the optimizer, moving your code in an IIFE we get the same result as with the onmessage event handler:

const test1 = () => {
  const workerScript = `
onmessage = 
function(event) 
{
 var x = event.data;
 var c = 0;
 const t1 = performance.now();
 for(var i = 0; i < x; i  ) c = c   Math.random();
 const t2 = performance.now();
 postMessage(t2 - t1);
}
`;
  const blob = new Blob([workerScript]);
  const worker = new Worker(URL.createObjectURL(blob));
  worker.postMessage(100000000);
  return new Promise((res) => worker.onmessage = (evt) => res(evt.data));
}

const test2 = () => {
  const workerScript = `
 var x = 100000000;
 var c = 0;
 const t1 = performance.now();
 for(var i = 0; i < x; i  ) c = c   Math.random();
 const t2 = performance.now();
 postMessage(t2 - t1);
`;
  const blob = new Blob([workerScript]);
  const worker = new Worker(URL.createObjectURL(blob));
  worker.postMessage(1000000);
  return new Promise((res) => worker.onmessage = (evt) => res(evt.data));
}
const test3 = () => {
  const workerScript = `
(function() {
 var x = 100000000;
 var c = 0;
 const t1 = performance.now();
 for(var i = 0; i < x; i  ) c = c   Math.random();
 const t2 = performance.now();
 postMessage(t2 - t1);
})()`;
  const blob = new Blob([workerScript]);
  const worker = new Worker(URL.createObjectURL(blob));
  worker.postMessage(1000000);
  return new Promise((res) => worker.onmessage = (evt) => res(evt.data));
}
test1()
  .then(console.log) // message handler
  .then(test2)
  .then(console.log) // main script
  .then(test3)
  .then(console.log) // IIFE

  • Related