MichaelK
MichaelK

Reputation: 101

Javascript Webworker postmessage is really slow even with short string messages

I am attempting to send a string to a webworker using postMessage. This consistently takes > 100ms to do. this is the relevant code in the main thread

return new Promise(function(resolve, reject) {
  let w = new Worker(<webworker_url>)
  w.onmessage = function(e) {
    resolve(e.data);
  }
  console.log(Date.now());
  w.postMessage('test text');
  w.onerror = reject;
});

logging the time immediately in onmessage within the webworker

onmessage = function(e) {
   console.log(Date.now());
   ...
}

the times shown in the console are over 100ms, switching browsers to chrome dev or chrome canary helps but doesn't bring it down past 50ms which is still really slow from my understanding.

Is my understanding about the speed of postMessage wrong? Or is my code wrong?

Upvotes: 1

Views: 2046

Answers (1)

Tom&#225;š Zato
Tom&#225;š Zato

Reputation: 53307

The problem is that you're creating a new WebWorker with every call to that promise. There's a lot of overhead with creating a web worker - browser needs to init new JS engine, parse the javascripts etc.

You need to cache the initialized worker somehow, or provide it to the promise. You will then need to make a system to determine which message belongs to which promise. Some starter idea:

let _cachedWorker = null;
let _uniqueMessageId = 0;
function _getWorker() {
  if(_cachedWorker == null) {
    _cachedWorker = new Worker(<webworker_url>);
  }
  return _cachedWorker;
}

function WorkerOperationPromise(messageData) {
  return new Promise(function(resolve, reject) {
    let w = _getWorker();
    const currentMessageId = ++_uniqueMessageId;
    w.addEventListener("message", function(e) {
      if(e.data.messageId == currentMessageId) {
        resolve(e.data.messageData);
        // You MUST! also remove this listener somehow
      }
    });
    w.postMessage({messageId: currentMessageId, messageData});
  });
}

Or use some RPC framework that already can do this.

Upvotes: 0

Related Questions