我已经在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 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。
答案 0 :(得分: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毫秒。
这些结果表明,数据传输几乎不需要时间(几乎与等待下一个事件循环一样快)。
所以您的瓶颈在另一个城堡,并且在消息传递部分没有任何要加快的事情。
请记住,如果您的主线程被阻止,从该主线程触发的处理程序也将被阻止。