Ускорение обмена сообщениями с веб-работниками - PullRequest
0 голосов
/ 16 апреля 2020

Я специально протестировал обмен сообщениями веб-работника в Chrome и получил результаты с задержкой около 50 мс для отправки и получения сообщения:

// Sender section

let imageData = mCtx.getImageData(0, 0, w, h);
let bitmapData = await createImageBitmap(imageData);
beforeAddBitmapFrame = performance.now();
videoWorker.postMessage({ action : 'addFrameBitmap', data: bitmapData }, [bitmapData]);


// Receiver section

videoWorker.onmessage = function (e) {
    let blob = e.data.data;
    beforeRenderBlobFrame = performance.now();
    let latency = (beforeRenderBlobFrame - beforeAddBitmapFrame); // 50ms
    if(latency > 10) {
       console.log('=== Max Latency Hit ===')
    }
    renderBlobTest(blob);
};

Это в основном тест oop, в котором изображение отправляется веб-работнику, и веб-работник просто отправит его обратно для расчета задержки. 50 мс здесь могут показаться пустыми, но если вы умножите его, как для видео с 30 кадрами в секунду, то математика, 50 ms x 30 frames = 1500 ms задержка (1,5 секунды), это много, учитывая, что это не передача по сети.

Что можно сделать, чтобы снизить задержку обмена сообщениями веб-работников?

[ОБНОВЛЕНИЕ] Для дальнейшего тестирования я выполнил простой тест "ping" для веб-работника с заданным интервалом

setInterval(function () {
  let pingTime = new Date().getMilliseconds();
  videoWorker.postMessage({ action: 'ping', pingTime : pingTime });
}, 500);

Затем сделал

if(e.data.pingTime) {
  let pongTime = new Date().getMilliseconds();
  console.log('Got pong: ' + ( pongTime - e.data.pingTime ))
}

Аналогичный результат выше, он в среднем составляет ~ 50 мс.

1 Ответ

0 голосов
/ 16 апреля 2020

Вы чувствовали себя в одной из ловушек микропроцессорного теста:

Никогда не запускайте ни одного экземпляра теста.

Первый запуск всегда будет медленнее, двигатель должен прогреться, в вашем случае должен быть сгенерирован весь поток Worker и инициализировано множество других вещей (список вещей, задерживающих первое сообщение, см. в этом Q / A ).
Также, один тест склонен сообщать о совершенно ложных результатах из-за некоторых внешних и не связанных событий (фоновое приложение решает выполнить некоторые операции именно в этот момент, включается сборщик мусора, событие пользовательского интерфейса, что угодно ...)

const videoWorker = new Worker( generateWorkerURL() );

let startTime;
const latencies = [];
const max_rounds = 10;

// Receiver section
videoWorker.onmessage = function (e) {
  const endTime = performance.now();
  e.data.close();
  const latency = (endTime - startTime);
  // store the current latency
  latencies.push( latency );
  if( latencies.length < max_rounds ) {
    performTest();
  }
  else {
    logResults();
  }
};
// initial call
performTest();

// the actual test code
async function performTest() {
  // we'll build a new random image every test
  const w = 1920;
  const h = 1080;
  // make some noise
  const data = Uint32Array.from( { length: w * h }, ()=> Math.random * 0xFFFFFF + 0xFF000000);
  const imageData = new ImageData( new Uint8ClampedArray( data.buffer ), w, h );
  let bitmapData = await createImageBitmap(imageData);
  // start measuring the time it takes to transfer
  startTime = performance.now();
  videoWorker.postMessage( bitmapData, [ bitmapData ] );
}

// when all the tests are done
function logResults() {
  const total = latencies.reduce( (total, lat) => total + lat );
  const avg = total / latencies.length;
  console.log( "average latency (ms)", avg );
  console.log( "first ten absolute values", latencies.slice( 0, 10 ) );
}

function generateWorkerURL() {
  const content = `onmessage = e => postMessage( e.data, [e.data] );`;
  const blob = new Blob( [ content ], { type: 'text/javacript' } );
  return URL.createObjectURL( blob );
}

Выполнение 1000 тестов приводит к в среднем <1,2 мс на тесты на моей машине (и 0,12 мс, если не генерировать новый ImageData каждый тест, т.е. без G C) , в то время как первый запуск занимает около 11 мс. <br>Эти результаты означают, что передача данных практически не занимает времени (это почти так же быстро, как ожидание следующего события l oop).

Таким образом, ваше узкое место находится в другом замке , и ускорять обмен сообщениями нечего.
Помните, что если ваш основной поток заблокирован, то и обработчики будут огонь из этого основного потока.

...