vue+openlayers地图聚合图层卡顿原因分析

868 阅读3分钟

问题描述

系统采用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对象中导致了卡顿。

原因分析

image.png

map对象比较大,本例中大致占用2M空间,图层聚合过程有大量节点属性变化,推测是大量的节点变化调用setter,触发watcher。

解决方案

!!!地图相关实例不要放到vue响应式数据中
!!!地图相关实例不要放到vue响应式数据中
!!!地图相关实例不要放到vue响应式数据中

重要的事情说三遍。

map对象可挂载windows全局变量下,使用组件内部非响应式数据对象,使用ref引用对象等。只要不是响应式的就行。该类问题不局限于openlayers,其他各类地图组件均会有同样问题。