web worker和主线程的数据交换效率初探

本文探讨了WebWorker中不同数据传输方式的性能表现,并通过实验对比了StructuredClone算法与Transferable对象之间的效率差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

web worker是浏览器的多线程机制,多用于处理不涉及DOM操作的密集计算任务,例如算法计算,数据请求处理等,我正在开发的开源地图引擎 maptalks.js 中对地图数据的处理就很适合放到web worker中(突兀的硬广 ^_^)。

web worker最大的优点是形式简单:

  • worker的运行上下文(context)与主线程独立,无法互相调用,避免了多线程编程中的线程锁等复杂机制
  • worker只能通过postMessage和onmessage与主线程交换数据

所以,worker程序的性能很大程度上取决于与主线程之间数据交换效率。

  • 默认情况下,postMessage中数据是采用结构化克隆(structrured clone)算法来实现跨进程传送的。
  • 引进Web Worker接口时,浏览器同时引进了Transferable和ArrayBuffer这一对好基友,当传送的数据为Transferable时,浏览器能通过只传送数据引用(指针),而不是结构化克隆(structrured clone)来极大的提高数据传送效率,具体可以参考google的 Transferable Objects: Lightning Fast!(需翻墙)。

问题

当传送数据结构不复杂时(类型化数组,字符串等),我们有两种可选的数据传送方式:

  • 直接用postMessage({ data })传送,让浏览器用structured clone算法拷贝数据到主线程
  • 参考谷歌文章,将数据先转化为ArrayBuffer(Transferable),然后直接传引用给主线程,无需structured clone

如果数据本身已经是类型化数组,毫无疑问方式二更好。

但如果有很多简单数据(类型化数组或字符串),将这些数据转化为ArrayBuffer后采用Transferable传送,相比浏览器的structured clone,哪个效率更高?

测试

为此,我写了一个jsperf测试程序

测试数据为100K字节的整数数组和200K字节的字符串数组,创建以下四个测试用例:

  1. 封装成对象,直接传送数据 (structured clone传送)
  2. 拷贝为新的数组后,封装成对象传送 (structured clone传送)
  3. 将数组转化为ArrayBuffer,转化方式用传统的遍历循环数据 (Transferable传送)
  4. 将数组转化为ArrayBuffer,转化方式用TypedArray.prototype.set批量转化 (Transferable传送)

测试结果取决于浏览器:

  • 在chrome 64和firefox 58下, 都是方式4最快,但chrome上方式3最慢
  • firefox下方式1,2最慢,与3,4差距很大
  • 在ie 11下,1最快,3最慢,但4与1的差距并不大

结论

  • 综合来看,数据结构简单时,转化成ArrayBuffer,用Transferable方式传送性能更好
  • ArrayBuffer的转化方式很重要,用Array.prototype.set,而不是循环遍历
  • 除了100K + 200K,也测试了其他数据,结论仍然成立

最后附上我本机的测试结果:

Chrome 64:

Firefox 58:

IE11:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值