浅析Echarts图表渲染导致内存泄漏的原因及解决方案

 更新时间:2023年10月22日 16:15:39   作者:anyup  
在今年某个可视化大屏项目中,出现了一个问题,项目在运行一段时间后,页面出现了崩溃,而且是大概运行几天之后,因为大屏项目是部署到客户现场大屏,长时间运行不关闭,小编认为 Echarts 图表渲染导致了内存泄漏,本文将深入分析这一问题,并提供解决方案

一. 引言

在今年某个可视化大屏项目中,出现了一个问题。项目在运行一段时间后,页面出现了崩溃,而且是大概运行几天之后,因为大屏项目是部署到客户现场大屏,长时间运行不关闭。报错问题如下图所示:

由于这个大屏页面是使用 Echarts 图表渲染的,整个页面就一个渲染地图的功能,没有多少耗费内存的操作。而 Echarts 作为一款强大的数据可视化库,被广泛应用于各种项目中,因此 Echarts 的稳定性也是经过广大开发者验证的,不会出现明显的 bug 问题。

然而,我们也知道,如果页面随着图表数量的增加和动态更新的需求,我们必然会考虑 Echarts 图表渲染导致的内存泄漏问题。因此,上面的问题我们按照这个猜想来往下走,认为 Echarts 图表渲染导致了内存泄漏,那么 Echarts 的什么操作会导致内存泄漏、甚至到页面崩溃呢?

本文将深入分析这一问题,并提供解决方案。

二. 问题背景

猜测原因

当我们使用 Echarts 来渲染大量图表时,会发现页面的内存占用不断增加,最终导致页面卡顿甚至崩溃。这是由于 Echarts 在图表渲染过程中产生的内存泄漏导致的。

而奇怪的是,自己在本地中测试的时候,从未有过崩溃的现象?但是在客户现场就出现了这种问题。

内存占用检测

为了能够实时监测网站运行过程中,我们在 Chrome 浏览器打开了内存性能分析,便于实时查看内存占用情况,发现运行内存占用并不是太大,我们监测过一段时间后发现,确实内存有时在稳定的增加,但是这点内存占用还不至于导致系统崩溃。

内存泄漏原因分析

  • 嵌套事件绑定:在 Echarts 图表中,每个图表都会绑定各种交互事件。如果我们正确地解绑这些事件,则会导致事件监听器无法垃圾回收,从而造成内存泄漏。

  • 大量的图表实例:如果我们在动态更新图表的过程中,每次都创建新的图表实例而不销毁旧的实例,就会导致内存占用不断增加。

  • 定时器未清理:如果我们在更新图表的过程中使用了定时器来控制刷新频率,但未能正确清理这些定时器,就可能导致内存泄漏。

三. 第一轮解决方案

因为可视化大屏项目代码不是我直接写的,我当时只不过是被临时抽过去提过几个建议而已,所以并没有深入的研读项目代码,所以这一轮解决方案可以定义为是在浪费时间,不过也并不是一点经验没有,一起来看一下吧。

初步解决

为了解决 Echarts 图表渲染导致的内存泄漏问题,我们采取以下措施:

  • 在绑定事件监听器时,要确保正确解绑,可以使用 Echarts 提供的off方法来取消事件定。

  • 在图表组件销毁之前,务必使用 dispose 函数销毁图表实例,以确保释放内存。

  • 在动态更新图表时,尽量复用现有的图表实例,而不是每次都创建新的实例。可以使用 Echarts 提供的setOption方法来更新图表数据和配置。

  • 如果使用了定时器来控制图表的刷新频率,必须在组件销毁前清定时器,可以使用clearIntervalclearTimeout来停止定时器。

  • 正确管理图表组件的生命周期,尽量避免不必要的渲染和更新操作。

初步验证

按照以上的初步解决方案,我们对流程进行了初步优化,主要进行了事件监听器的绑定与解绑优化、销毁定时器、dispose 函数销毁图表实例等操作。

等这些优化操作完成后,我们又部署到自己的系统进行初步验证,发现内存占用确实变的小了,但是等到运行长时间来看,内存还是有上升的趋势。因此我断定,没有找到根本原因解决。

果然,运行了大概有五天的时间,浏览器还是顶不住了,系统再一次不工作了。

四. 第二轮解决方案

可能原因

由于这个大屏项目是其他同事开发的,具体的代码我并不太清楚。因此,先前只是提供了一些建设性的建议,没想到同事修改完成后还是没有解决了根本问题。所以可能必须要完全读懂项目的代码才能找到根本原因。

果然,看了几遍代码后发现了一些端倪,页面部署上之后是不会再进行操作了,数据会自动定时刷新,地图数据也会自动刷新,因此,问题就出现在这了。

猜想

多次调用 Echarts.init,项目中这一段代码写的确实有问题,写了个定时器,每次刷新数据时,都需要调用 Echarts init,并且销毁时 clear 和 dispose 方法使用不当造成,定时器循环重绘 Echarts 图表导致内存一直升高,最终导致了浏览器崩溃。

解决方案

通过 Echarts init 方法创建 Echarts 实例,如果代码没有做优化,echarts 实例就会越来越多,占用大量内存,有以下两种方法可以避免这种情况:

第一种:使用 Echarts init 之前先判断是否存在实例

const chart = Echarts.getInstanceByDom(document.getElementById(dom));
if (chart === undefined) {
  chart = Echarts.init(document.getElementById(dom));
}

第二种:如果 Echarts 存在,先 dispose 销毁后,再调用 init

const chart = Echarts.getInstanceByDom(document.getElementById(dom));
if (chart) {
  Echarts.dispose(chart);
}
chart = Echarts.init(document.getElementById(dom));

验证

使用上述的代码进行优化,再结合第一轮的代码优化后。系统又重新部署了,监测系统内存状态,初始的内存占用大小和之前的相差不大。不过观察一段时间后,内存没有持续升高的趋势,还算比较稳定。又这样运行了大概有一周左右,发现内存占用仍然稳定,系统也没有出现过崩溃的问题。因此可以断定,应该是优化好了。

五. 总结

Echarts 图表渲染导致的内存泄漏问题是我们在使用 Echarts 时经常遇到的挑战之一。

在 Echarts 做图表开发时,避免内存泄漏的几点操作主要有以下几个方面:

  • 多次调用 Echarts.init 会导致内存泄漏,应当在恰当时机销毁已经存在的 Echarts 实例,使用 clear() 和 dispose() 手动清理,区别在于:

    • clear()不会销毁实例,只是重新绘制图形,
    • dispose()会销毁实例,需要重新构建 ECharts 对象
  • 在动态更新图表时,尽量复用现有的图表实例,而不是每次都创建新的实例。可以使用 Echarts 提供的setOption方法来更新图表数据和配置。

  • 在绑定事件监听器时,要确保正确解绑,可以使用 Echarts 提供的off方法来取消事件。

通过深入分析内存泄漏的原因,并采取相应的解决方案,我们可以有效地解决这一问题,确保应用的稳定性和性能。

以上就是浅析Echarts图表渲染导致内存泄漏的原因及解决方案的详细内容,更多关于Echarts图表渲染导致内存泄漏的资料请关注脚本之家其它相关文章!

相关文章

  • 简单实现JS计算器功能

    简单实现JS计算器功能

    这篇文章主要教大家简单实现JS计算器功能,实现小数点校验,重复计算,以及大量更符合用户体验的操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • JavaScript中获取随机数的几种方法小结

    JavaScript中获取随机数的几种方法小结

    本文总结了JavaScript中获取随机数的几种方法,包括Math.random()、生成指定范围的随机数和从数组中随机选择一个元素,具有一定的参考价值,感兴趣的可以了解一下
    2025-02-02
  • 使用gulp搭建本地服务器并实现模拟ajax

    使用gulp搭建本地服务器并实现模拟ajax

    这篇文章主要给大家介绍了如何使用gulp搭建本地服务器并实现模拟ajax的相关资料,文中介绍的非常详细,相信对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-04-04
  • js中的数组转树型结构方式

    js中的数组转树型结构方式

    这篇文章主要介绍了js中的数组转树型结构方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • javascript常用的数组过滤和查找方法总结

    javascript常用的数组过滤和查找方法总结

    这篇文章主要介绍了javascript常用的数组过滤和查找方法的相关资料,这些方法各有特点,适用于不同的数据处理场景,大家可以根据需求选择不同的方法,需要的朋友可以参考下
    2024-12-12
  • JavaScript中立即执行函数实例详解

    JavaScript中立即执行函数实例详解

    javascript和其他编程语言相比比较随意,所以javascript代码中充满各种奇葩的写法,有时雾里看花,当然,能理解各型各色的写法也是对javascript语言特性更进一步的深入理解。这篇文章主要给大家介绍了关于JavaScript中立即执行函数的相关资料,需要的朋友可以参考下。
    2017-11-11
  • javascript笔试题目附答案@20081025_jb51.net

    javascript笔试题目附答案@20081025_jb51.net

    网上找的javascript笔试题目,留档给自己作参考。
    2008-10-10
  • 微信小程序实现长按删除图片的示例

    微信小程序实现长按删除图片的示例

    本篇文章主要介绍了微信小程序实现长按删除图片的示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • JS加ASP二级域名转向的代码

    JS加ASP二级域名转向的代码

    JS加ASP二级域名转向的代码...
    2007-05-05
  • 详解如何准确判断JavaScript中的数据类型

    详解如何准确判断JavaScript中的数据类型

    JavaScript中,我们经常需要判断数据类型以便于正确地处理数据,本文将介绍JavaScript中的数据类型判断技术,包括typeof操作符、instanceof操作符、Object.prototype.toString方法以及ES6新增的一些数据类型判断方法,需要的朋友可以参考下
    2023-08-08

最新评论