大屏页面崩溃排查(Too many active WebGL contexts. Oldest context will be lost)
1 问题背景
顾问反馈大屏在反复切换的过程中,页面会出现白屏,导致后续的操作无法进行,只能通过刷新页面才能恢复正常。
- 我们的页面类似于这样的布局(下方的是直接从网络上找的截图)
- 点击下方红线框住的区域,可以展示不同的图表(echarts图表)
- 区别在于我们的主区域不是图片,用的是基于cesium封装的地图(webgl)
2 问题复现
测试同事经过几分钟的快速切换导航后,复现了,报错了如下内容
问题如果复现了,其实就解决了一半了
3 查找问题
经过复现后,发现除了上面的报错,每当页面崩溃前,chrome总会有下方的warning。然后基于cesium封装的地图就会崩溃。
翻译成中文:警告:目前有了太多激活的webgl上下文,最早的上下文将会丢失
4 排查问题
经过和地图组的人沟通,得到一个结论WebGL一个页面上最多有16个实例
- 怀疑echarts在下方菜单切换过程中,没有进行销毁
检查了代码中的echats的页面在销毁的时候,发现都进行了dispose,排除了这个的原因
- 怀疑起echarts的3d的饼状图
之前设计师设计了一个3d的饼状图,参考了 3d柄图环图,一个页面上有多这个组件。
效果如下:
5 锁定组件进行验证
- 先把一个页面上的所有组件改为上方的饼状图,然后点击导航栏,频繁进行切换,
- 页面很快就崩溃了,然后检查这个组件在页面销毁的时候,是否进行dispose
检查后,发现没有,添加后进行测试,问题依旧 - 继续检查发现这个组件导入了echarts-gl,就去ecahrts的github的issues进行搜索,终于找到了一个类似的问题
github.com/ecomfe/echa…
加入了类似的代码,进行验证后解决了此问题
6 总结
- chrome浏览器中最多有16个webgl的实例。当过多的时候,会把最早创建的实例销毁
- 当使用echarts在页面销毁的时候及时进行dispose,释放上下文
- 当使用echarts-gl的时候,调用dispose的时候是不生效的,需要找到页面上的canvas,然后手动将上下文释放,类似下方的代码
const canvasArr = myChart.getDom().getElementsByTagName('canvas');
for(let i=0; i<canvasArr.length; i++){
canvasArr[i].getContext('webgl').getExtension('WEBGL_lose_context').loseContext()
}
7 参考文档
作者:pauldu
来源:juejin.cn/post/7351712561672798260
来源:juejin.cn/post/7351712561672798260