更快的网络工作者消息传递

问题描述 投票:0回答:1

我已经在Chrome中专门测试了网络工作者消息传递,并获得了大约50ms的延迟来发送和接收消息:

// 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);
};

这基本上是一个循环测试,其中将图像发送给Web Worker,Web Worker会将其发送回去以计算延迟。乍一看,这里的50毫秒可能什么都不是,但是如果像30 FPS的视频那样乘以50毫秒,那么算一下,50 ms x 30 frames = 1500 ms延迟(1.5秒)就算不上网络传输了很多。

如何减少Web Worker消息传递的延迟?

[UPDATE]为了进一步测试,我以给定的时间间隔对网络工作者进行了简单的“ 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 ))
}

高于它的类似结果平均为〜50ms。

javascript performance web-worker
1个回答
0
投票

[您在一个微型基准陷阱中感到:

永远不要运行测试的单个实例。

第一次运行总是会变慢,引擎必须预热,在这种情况下,必须生成整个Worker线程,并且必须初始化很多其他内容(有关延迟的情况,请参见this Q/A第一条消息)。另外,由于某些外部和不相关的事件(后台应用程序正决定在此时执行某些操作,垃圾收集器启动,UI事件等),单个测试很容易报告完全错误的结果。]

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毫秒(如果每个测试(例如,不使用GC)不生成新的ImageData,则平均为0.12毫秒),而第一次运行大约需要11毫秒。这些结果表明,数据传输几乎不需要时间(几乎与等待下一个事件循环一样快)。

所以您的瓶颈在另一个城堡中,并且在消息传递部分没有什么可以加快的。请记住,如果您的主线程被阻止,从该主线程触发的处理程序也将被阻止。

© www.soinside.com 2019 - 2024. All rights reserved.