|
楼主
吾爱游客
发表于 2024-11-15 11:02
|自己
1、申 请 I D:Resthx
2、个人邮箱:905459569@qq.com
3、原创技术文章:记录一次echarts图表大数据量轮询刷新页面卡死问题的优化
原创文章连接https://blog.csdn.net/qq_3527080 ... 1001.2014.3001.5502
全栈开发者,擅长java,rust,javascript等语言,linux系统运维,容器化,集群等,个人博客名字:爱音乐的程序猿,链接:https://blog.csdn.net/qq_35270805
目前已有70多篇个人原创文章,总共24w阅读量
记录一次echarts图表大数据量轮询刷新页面卡死问题的优化
项目场景:
在我们的项目架构中,集成的Echarts图表组件采用了折线图,业务需求即每300毫秒自动更新图表上的数据,并且每一次的数据点数量达到了约700个,折线图刷新的很快,每300毫秒就要刷新数据
问题描述
开发过程中发现在这种数据量请求频率下,大概2个小时左右就会导致整个页面卡死,无法操作。问题很严重
原因分析:
经过详细的排查发现是echarts图表在大数据量下确实会有这种问题。我们业务虽然只有两个图标,但更新频率很快,也遇到了此问题。原因是多方面的,一个是配置不高的电脑cpu撑不住,一个echarts也有内存问题,在大数据量频繁刷新内存和cpu撑不住,直接导致页面崩溃。经过考虑采取先不降低频率,先优化图表方式。解决这个问题需要从多方面下手
解决方案:
1.解决定时轮询稳定性:将定时轮询单独放在一个线程中,稳定定时任务运行效率参考代码:
// worker.js self.addEventListener("message", function (event) { const { task } = event.data; console.log("worker", task); if (task === "getChartData") { //创建定时任务 if (!self.timerThread) { self.timerThread = this.setInterval(async () => { self.postMessage({}); }, 300); } }else if (task === "stop") { //清除定时任务 if (self.timerThread) { this.clearInterval(self.timerThread); self.timerThread = undefined; } }});
调用
stopComputation(){ if (this.worker != null) { this.worker.postMessage({ task: 'stop'}); this.worker.terminate(); this.worker = null; } }, startTimer(){ if (this.worker != null) { this.stopComputation() } this.worker = new Worker(new URL('./chartthread.js', import.meta.url)); this.worker.postMessage({ task: 'getChartData'}); this.worker.onmessage = async () => { console.log('Worker has been getVibration...............................'); this.getVibration() }; // 清理 Worker this.worker.onclose = function() { console.log('Worker has been terminated.'); };
修改之后发现发现有效果,但是效果不明显,最后还是卡死
2.将echarts实例单独提取到vue外部,避免vue多余监听浪费性能具体代码
<script>import elementResizeDetectorMaker from 'element-resize-detector' // 尺寸监听组件//设置此处会被多个vue组件公用,所以用key,value方式保存各个组件页面的实例,避免echarts实例公用let echartObject = {}export default { .......此处省略部分代码........ data () { return { options: {}, chartInstanceIndex: null, //图表实例 timer: null } }, mounted () { //随机8位数 this.chartInstanceIndex = Math.random().toString(36) this.timer = setInterval(() => { this.initChart() }, 60000) this.initChart() const erd = elementResizeDetectorMaker() // 为了健壮性,可以考虑一下这里获取dom元素进行一个判断,如果没有获取到dom元素就不进行监听,这里就这样了 erd.listenTo(document.getElementById(this.id), (element)=> { if (echartObject[this.chartInstanceIndex != null && echartObject[this.chartInstanceIndex != undefined) { echartObject[this.chartInstanceIndex.resize() } }) }, methods: { initChart() { if(!document.getElementById(this.id)){ return } if (echartObject[this.chartInstanceIndex != null && echartObject[this.chartInstanceIndex != undefined) { echartObject[this.chartInstanceIndex.dispose() echartObject[this.chartInstanceIndex == null } echartObject[this.chartInstanceIndex = this.$echarts.init(document.getElementById(this.id)) this.options = {...省略....} echartObject[this.chartInstanceIndex.setOption(this.options) }, updateData () { if(echartObject[this.chartInstanceIndex != null){ echartObject[this.chartInstanceIndex.setOption({ series: [{ data: this.yData }, }) } } }}</script>
3.关闭动画可提高性能
官网配置项
options.animation改成false
4.配置折线图在数据量远大于像素点时候的降采样策略
官方文档:官方文档
有几种采样算法,此处我才用了第一种lttb算法。经过前面几个方法优化效果明显,但经过大约4个小时后还是撑不住,最终使用了下面的方法成功解决问题
5.定时删除并重新创建echarts实例
如果试了上面的方法还是不行。那么最后一种方式可以试一下。原理是定时重新创建并清除旧的实例,相当于重新初始化一次
代码参考:
<script>import elementResizeDetectorMaker from 'element-resize-detector' // 尺寸监听组件let echartObject = {}export default { ............................... data () { return { options: {}, chartInstanceIndex: null, //图表实例 timer: null } }, destroyed() { if (this.timer!=null) { clearInterval(this.timer) this.timer == null } }, mounted () { //随机8位数 this.chartInstanceIndex = Math.random().toString(36) this.timer = setInterval(() => { //定时重新初始化 this.initChart() }, 60000) this.initChart()........................... }, .............. methods: { initChart() { if(!document.getElementById(this.id)){ return } if (echartObject[this.chartInstanceIndex != null && echartObject[this.chartInstanceIndex != undefined) { echartObject[this.chartInstanceIndex.dispose() echartObject[this.chartInstanceIndex == null } echartObject[this.chartInstanceIndex = this.$echarts.init(document.getElementById(this.id)) this.options = {........................} echartObject[this.chartInstanceIndex.setOption(this.options) }, updateData () { if(echartObject[this.chartInstanceIndex != null){ echartObject[this.chartInstanceIndex.setOption({ series: [{ data: this.yData }, }) } } }}</script>
经过该方式优化后成功解决了长时间运行页面卡死的问题 |
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|