postMessage from worker: many small msgs or single large

Benchmark created by Andrew Petersen on


Description

Given a worker, what are the effects of making multiple postMessage calls with single objects, or a single postMessage call with an array, or even a custom string encoding?

Setup

function forTheWorker() {
    
      var id = 0;
      var mode = '';
    
      onmessage = function(ev) {
        if (ev.data.mode) mode = ev.data.mode;
        postUpdates();
      }
    
      function makeUpdate() {
        var msg = {
          type: 'boid update',
          id: ++id,
          x: Math.random(),
          y: Math.random(),
          radius: 8
        };
        return msg;
      }
    
      function makeStringUpdate() {
        var msg = 'type:boid update'
          + ',id:' + (++id)
          + ',x:' + Math.random()
          + ',y:' + Math.random()
          + ',radius:' + 8;
        return msg;
      }
    
      function postUpdates() {
        var i, max = 400, msgs;
        if (mode === 'batched') {
          msgs = [];
          for(i = 0; i < max; i++) {
            msgs.push(makeUpdate());
          }
          postMessage({ type: 'boid updates', updates: msgs });
        }
    
        if (mode === 'batched string') {
          msgs = [];
          for(i = 0; i < max; i++) {
            msgs.push(makeStringUpdate());
          }
          postMessage({ type: 'boid updates', updates: msgs });
        }
    
        if (mode === 'singles') {
          for(i = 0; i < max; i++) {
            postMessage(makeUpdate());
          }
        }
    
        if (mode === 'singles string') {
          for(i = 0; i < max; i++) {
            postMessage(makeStringUpdate());
          }
        }
    
        postMessage('updateend');
      }
    }
    
    var jssrc = '(' + forTheWorker.toString() + '())';
    var jsblob = new Blob([jssrc], { type: 'text/javascript' });
    var jsURL = window.URL.createObjectURL(jsblob);
    
    var w = new Worker(jsURL);
    
    function tick(mode) {
      w.postMessage({ mode: mode });
    }
    
    var currentDeferred = null;
    function useDeferred(deferred) {
      currentDeferred = deferred;
    }
    
    w.onmessage = function(ev) {
      if (currentDeferred && ev.data === 'updateend') {
        currentDeferred.resolve(ev.data);
      }
    
      var parsed;
    
      if (typeof ev.data === 'string' && ev.data !== 'updateend') {
        parsed = parseString(ev.data);
        //console.log('parsed', parsed);
      }
    
      if (ev.data.updates && typeof ev.data.updates[0] === 'string') {
        for (var i = 0; i < ev.data.updates.length; i++) {
          parsed = parseString(ev.data.updates[i]);
          //console.log('parsed', parsed);
        }
      }
    }
    
    function parseString(str) {
      var parts = str.split(',');
      var obj = {};
      var part;
      for(var i = 0; i < parts.length; i++) {
        part = parts[i].split(':');
        obj[part[0]] = part[1];
      }
      return obj;
    }

Test runner

Ready to run.

Testing in
TestOps/sec
batched
// async test
useDeferred(deferred);
tick('batched');
 
ready
singles
// async test
useDeferred(deferred);
tick('singles');
 
ready
batched string
// async test
useDeferred(deferred);
tick('batched string');
 
ready
singles string
// async test
useDeferred(deferred);
tick('singles string');
 
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.

  • Revision 1: published by Andrew Petersen on
  • Revision 2: published by Andrew Petersen on
  • Revision 3: published by Andrew Petersen on
  • Revision 4: published on
  • Revision 5: published by Alexander on