在WebGL应用中使用Web Worker提升效率

Web Worker介绍:

  js本身是一种单线程设计,我们无法在同一时刻并行运行多个脚本。虽然可以用setInterval,setTimeout方法来模拟多线程,但实际上这些方法都是存在于主线程使用的一个事件循环里,一旦存在一个耗时操作,就会牵制主线程的操作,导致页面卡顿。Web Worker通过引入类似线程的机制使这种问题得到了解决,通过在当前js主线程中使用worker类加载一个js文件来开辟一个新线程,起到互不阻塞执行的效果。这个js worker运行在另一个全局上下文中,不同于当前的window,所以不能用window变量来获取当前全局的范围。

Web Worker的使用限制:

* 没有共享的状态

 在创建的每一个工作线程里,都无法直接访问主线程中的数据,主线程也无法直接访问工作线程中的数据,它们之间的通信都需要通过消息API来实现。

* 没有DOM访问权限

 在工作线程里是无法访问DOM的,也就相应的没有window对象和document对象。

* 同源策略

 只能创建和当前脚本同源的工作线程

* 浏览器兼容性

什么时候需要Web Worker:

  • 当需要一个js脚本进行大量的复杂计算时候,通过postMessage和onmessage进行通信
  • 功能模块化。importScripts这个方法只能在worker线程中执行,该方法可以在worker线程中引入多个脚本,则该线程可以使用所引入脚本中的任意变量和函数。
  • 当需要执行一个不断向后台发送更新请求的时候,可以将这个过程放到工作线程里,然后将结果返回给主线程。

Web Worker使用:

①创建一个线程:
通过new一个Worker实例来创建一个线程,构造函数参数传递一个指向js文件资源的url。

const worker = new Worker('a.js');

②与一个线程通信:
为了在页面主程序接收从专用线程传递过来的消息,我们需要使用工作线程的onmessage事件处理器。通信的数据不止是字符串,也可以是数组或者对象。
主线程:

onload =function(){
    var worker =new Worker('a.js');
    worker.onmessage = function (evt) {//接收子线程消息
        console.log(evt.data); //hello received
    };
    worker.postMessage("hello")//向子线程发送消息
}

子线程:

onmessage =function(event) { //接收主线程消息
    let str = event.data;
    postMessage(str+" received"); //发送子线程消息
};

在主线程中,消息事件依托于创建出来的worker对象,而在工作线程中,消息事件依托于全局对象。

当工作线程完成了任务后,需要调用terminate方法来释放内存和避免僵尸线程的情况:

worker.terminate();

工作线程的数量问题

  通常情况下是读取navigator.hardwareConcurrency的数值,它表示机器最多可以并行执行的任务数量。例如下图返回的数值是4,则可以起4个web worker来进行处理。当然也可以起更多的web worker,但是多个线程的切换以及起线程的消耗就会比较大。
image_1bgn2s9gv10otmb71e2jh5g1lil9.png-7.4kB

WebGL上Web Worker的使用

  WebGL里经常会对大量顶点数据和索引数据进行计算,由于js单线程的原因,很容易造成堵塞,性能低下。通过web worker可以让js在后台解决这些问题。
  worker线程与主线程的数据传递使用的是结构化克隆,当数据量非常大的时候耗时严重,需用通过序列化的方式(JSON.stringfy)来传递数据。经测试,我起了四个线程来传递json对象,不序列化的时候是602ms,使用序列化的方式传递是186ms,性能明显提升。
  另外,针对webgl的数据类型大多都是arraybuffer类型,web worker中有一个非常实用的参数,那就是Transferable Objects。一旦对象是 Transferable 的,那么传递过程不再使用结构化克隆,而是按引用传递,这就避免了克隆导致的额外开销。只有诸如 ArrayBuffer、ImageBitmap 这样的二进制数据类型才可以。
  在Cesium当中,关于大数据量顶点的处理就是采用web worker来处理的。Cesium提供了一个TaskProcessor类来自定义一个工作线程,该类实际上就是包装了一个web worker,通过scheduleTask方法来定义异步任务。

参考资料
1.https://mp.weixin.qq.com/s?__biz=MzIzNDE0NjMzOQ==&mid=2653923832&idx=1&sn=25621f89fcd712b408634d53cd4a273a&chksm=f321d6b4c4565fa224e152ba8ded4abb599b9412abd8e8f201c30b4bfc1d0e33d08eb455694a&mpshare=1&scene=23&srcid=0516nZgoMT8Yjri8Vc1N5ug1#rd
2.https://juejin.im/entry/591946e0da2f60005df4ce5b

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搞GIS图形的sky.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值