问题描述
系统采用vue2+openlayers4搭建。地图加载常规点位与区域面图层,点图层进行了聚合。聚合采用ol-ext中的animatedcluster。当点位超过500以后就会明显卡顿,首屏响应时长20s。
排查过程
mindmap
排除思路
OL
聚合图层
点位数量
自定义图层效果
其他图层
耗时过程
其他
接口请求超时等待
分析性能瓶颈
业务最简化验证
独立Demo分析
OL
-
聚合图层
关闭图层聚合效果,加载效率明显提升。打开聚合效果图层渲染10s以上。按照常理推断,500个点位数据聚合不至于这么慢。为了验证推断使用在线demoAnimated clusters做对比验证。配置6000个点位依然可以秒加载。 -
点位数量
通过控制点位数量,加载耗时与点位数量线性正相关。 -
自定义图层效果
关闭图层自定义图标、动画效果等,加载效率无明显变化。 -
其他图层
地图仅加载一个聚合图层,加载效率无明显变化。 -
耗时过程
既然前面步骤以排查到是图层开启聚合引起,那就在图层初始化、图层加载、地图渲染等环节加日志计算耗时,走查代码梳理处理逻辑。此时找到一个性能瓶颈点,点Layer的Feature是单个添加,导致图层Source持续变化、进而持续触发聚合运算。把Feature改成批量添加
,然而欣喜不足1分钟,虽然性能有所提升,但是地图渲染完成执行回调后依然会卡顿10s以上。
其他
-
接口请求超时等待
检查页面加载过程中网络请求数据,卡顿过程无网络请求。 -
分析性能瓶颈
首先通过chrome开发者工具Performance
工具检查性能瓶颈。录制过程发现地图底图加载完成后页面录制结束。逐帧加载均正常,底图加载完成后的卡顿过程未能录制到。 使用vue devtool
检查组件渲染情况,组件渲染均是毫秒级,未发现异常。 使用任务管理器查看卡顿过程资源占用情况,主要是CPU占用高
。此时初步判定是js的业务逻辑存在大量运算导致卡顿。
-
业务最简化验证
把业务中与地图无关的页面元素、ws请求等全部屏蔽。依旧卡顿。 -
独立Demo分析
万般无奈,从头开始。搭建独立应用仅加载一个聚合图层,使用完全相同的数据源。测试结果几乎秒加载。现在可以明确排查方向了,是业务框架使用的问题,与openlayers无关。通过对比发现是map对象挂载到了组件的data对象中导致了卡顿。
原因分析
map对象比较大,本例中大致占用2M空间,图层聚合过程有大量节点属性变化,推测是大量的节点变化调用setter,触发watcher。
解决方案
!!!地图相关实例不要放到vue响应式数据中
!!!地图相关实例不要放到vue响应式数据中
!!!地图相关实例不要放到vue响应式数据中
重要的事情说三遍。
map对象可挂载windows全局变量下,使用组件内部非响应式数据对象,使用ref引用对象等。只要不是响应式的就行。该类问题不局限于openlayers,其他各类地图组件均会有同样问题。