webworker的传值⽅式以及耗时对⽐
背景
前⼀阵⼦开发的项⽬pptx 导⼊, 由于⾃⼰的代码问题,引起了个性能问题,⼀个 40p 的 pptx ⽂件,转换成 json 数据,⼤概要耗时 60s+ ,虽然后⾯发现是某个使⽤频率⾮常⾼的函数内部,⽤了new Function 构造函数造成的(所以这⾥顺便提醒⼀下,如果你很在乎⼏毫秒的差距的话,建议谨慎使⽤哈),但是在优化的过程中,⼀度怀疑是性能达到了瓶颈,所以尝试了使⽤ web worker 去优化,由于是⽂件,⼀般内容都⽐较⼤,发现 web worker 在传值这块占⽤了⼤部分的时间,所以想开这篇来详细聊聊.
两种传值⽅式
关于 web worker 的基本⽤于以及传值⽅式,⽹上以及有⼀⼤堆介绍了,这⾥就不赘述了,这⾥我们重点来看⼀下同⼀个⽂件⽤两种⽅式来传值,会有多⼤的差别,这边随意从电脑⾥⾯了⼀个 96MB 的 PSD ⽂件来测试.
主线程
fetch('./case.psd').then(file => {
return file.blob();
})
.then(blob => {
return new Promise(resolve => {
let fileReader = new FileReader();
resolve(sult);
}
})
})
.then(buf => {
let worker = new Worker('1.js');
console.time('计算时间');
worker.postMessage(buf);
console.timeEnd('计算时间');
}
})
worker(⼦)线程, 这⾥为了避免不必要的因素⼲扰,worker 线程⾥⾯什么也不做,在收到消息后,直接 post ⼀个消息回去
postMessage(0);
}
这边我直接⽤ FileReader 的 readAsArrayBuffer,读出来是⼀个长度为 96,138,230 的字符串,长度⼤概 0.96 亿, 耗时⼤概 70ms 左右(同⼀个台电脑取 10 次平均值,下同)
我们稍微改⼀下上⾯主线程的代码,改⽤转移数据的⽅式
- worker.postMessage(buf);
+ worker.postMessage(buf, [buf]);
同样的数据, 耗时⼤概 17ms 左右,这 17ms 好像是个固定值,我尝试换了个 800MB+ 的⽂件和⼀个⾥⾯啥都没有的空⽂本⽂件,⼤概都是这个时间.
不同的数据类型,⽤值传递的耗时也是不⼀样的
fetch('./case.psd').then(file => {
return file.blob();
})
.then(blob => {
return new Promise(resolve => {
let fileReader = new FileReader();
resolve(sult);
}
})
})
.then(str => {
console.log(str.length);
let worker = new Worker('1.js');
console.time('计算时间');
worker.postMessage(str);
console.timeEnd('计算时间');
}
})
这⾥我们改⽤ FileReader 的 readAsText,读出来是⼀个长度为 95,855,954 的字符串,长度⼤概 0.95 亿, 耗时⼤概 118ms 左右,同样我换了上⾯那个⾥⾯啥都没有的空⽂本⽂件,耗时也是 17ms 左右.
那我们试试⽤ readAsDataURL 看看读出来的数据要多久
fetch('./case.psd').then(file => {
return file.blob();
})
.then(blob => {
return new Promise(resolve => {
let fileReader = new FileReader();
resolve(sult);
}
})
})
.then(str => {
console.log(str.length);
let worker = new Worker('1.js');
console.time('计算时间');
worker.postMessage(str);
console.timeEnd('计算时间');
}
})
读出来是⼀个长度为 128,184,345 的字符串,长度⼤概 1,28 亿, 耗时⼤概 85ms 左右(虽然字符串长度更长,但是耗时却更短)
以上耗时,均为主线成向 worker 线程单向传递数据的耗时.
结论
1. 转移数据⼏乎是零开销(因为和传递空字符串的耗时是差不多的).
2. 值传递的话,不同的数据类型,耗时也有差别,ArrayBuffer < base64 < 普通字符串.
3. postMessage 传递消息,除了发送数据的耗时外,还有其他开销(就是上⾯的 17ms). 当然每台电脑性能不⼀样,耗时也是不⼀样的,不过按
⽐例来看,这个占⽐还挺⼤的.
关于转移的缺点, ⽹上也是有很多的, 这⾥也就不啰嗦了, 总结⼀句就是数据⽆法同时在2个线程上使⽤.
另外个⼈觉得如果是普通的数据,为了转移⽽去转换成Transferable objects的话, ⼤部分情况下是划不来的, 因为你需要在花在编码解码上的时间,会⽐直接传递花的时间多.
另外, 如果你是要⽤⼦线程处理图⽚的话, ImageBitmap格式配合最近新鲜出炉的OffscreenCanvas也许是不错的选择.前提是你不需要考虑兼容性问题.
字符串长度web最后是⼴告时间
我们40⼈的前端团队常年招兵买马中,在厦门的和想来厦门的童鞋们,不要吝惜你的简历,使劲砸过来邮箱:nuoya@gaoding, 期待你⼀起来稿事

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。