javascript - 如何在React中使用可变数据和实时图表实现最佳性能?

标签 javascript reactjs highcharts chart.js mobx

在过去的几周中,我对不同的图表库(尤其是Highcharts和Chart.js)进行了很多研究和试验,试图从中获得最佳性能,但结果令人失望。

可变性与不可变性:

首先,我决定放弃Redux,因为在数据/状态部分,我将所有数据点作为对象以[{x: sometimestamp, y: somenumber}]的形式存储在数组中

我放弃使用Redux作为状态容器,因为每次插入都会创建一个副本,因此在大规模情况下效果不佳。想象一下,复制一个100000个对象的数组,而您只需要在数组的末尾推送一个新的数据点对象。

同样,当到达(用户定义的)maxCount时,我将数组中的第一项移到了新项,同时将其推到末尾。这样,图表就“前进”了。

由于Redux的做事方式一成不变,因此并未完全减少,因此我选择了MobX。数据对象的可变状态正在按预期的方式移动和推送,所以现在我的唯一工作是尝试在每次有新数据到达时(在实际代码中大约每秒)将其呈现在图表组件中。

用例

因此,假设您每秒存储一个新的数据点24小时= 86400个数据点。那是极端的情况,通常我在移动的实时图表上不需要超过3600点(最近一小时)。有时候,尽管它对多个系列有用(通常为2-5,但实际上最多为10,这意味着36000分)。

通常,我会同时在屏幕上显示2-4个图表,每个图表都支持上述多个序列,并且每当新数据到达时,它们都会每秒更新一次。

来自基准的观察

现在,当我尝试显示一个少于2000点的图表时,我发现CPU利用率很高。即使禁用了动画,即使获得20分,该百分比似乎也有点过高。

React方式,vs ref + lib内部API /突变

很长一段时间以来,我一直很困惑,认为处理图表的反应方式是通过传递数据作为 Prop 。到目前为止还不错。我的问题是,如果您复制整个数据点数组,此数据属性只能由react.render识别为“已更改”并因此被重新呈现。这适用于小型数组,但不适用于数千个对象。

我试图做一个回购在这里显示:

ChartJs(反应方式)版本:https://github.com/BruceL33t/mutable-high-performance-real-time-charts-in-react/tree/chartjs-reactish

因此,使用MobX和可变数据,我寻求找到一种解决方案,可以避免每次更新都必须复制数据点。我能看到的唯一真正的解决方案是对图表库进行引用,并直接调用其内部api addPoint(point)(highcharts)或datasets[0].data(chartjs),然后直接在图表上调用redraw()/ update()。这样,组件在初始渲染之后将不会使用react的render函数。

我本以为这样做会更快,因为我们“更接近金属”并直接对图表数据进行了变异,但是我没有看到使用ref 真正的性能改善。

Chartjs 版本:https://github.com/BruceL33t/mutable-high-performance-real-time-charts-in-react/tree/master

Highcharts 版本:https://github.com/BruceL33t/mutable-high-performance-real-time-charts-in-react/tree/highcharts

尝试上面的示例

在index.js中,尝试将间隔从1000毫秒缩短至100毫秒(第103行),并将第90行的maxSize设置为Sensor(2000),然后在任务管理器打开的情况下运行,并关闭所有其他标签,并监控CPU使用情况 Chrome 。如您所见,当我们接近2000个数据点时,我们的CPU使用率接近60%。再次-这是没有动画。对于动画,它从40开始并从那里开始。

关于提高性能(降低CPU使用率)的任何想法

CPU每秒在 Canvas 上移动点是否需要做很多工作,或者我做错了什么?您是否知道其他任何图表库可以处理每秒几千个点的实时图表?以及您通常如何采取从MobX或其他方式获取可变数据点数组并将其呈现在React中的图表中的方法?在与React脱离网格以寻求更多“裸机”电源时应遵循的任何良好做法。除了使用ref或良好模式,还有其他方法吗?

编辑:

尽管我尚未对其进行测试,但是从外观上看,以下图表的性能似乎比到目前为止遇到的其他图表库要好得多。

  • rgraph
  • Canvasjs
  • d3
  • Dygraphs

  • 我现在将对其进行测试,并在对其进行尝试后进行更新。

    最佳答案

    每次移动数组时,都需要移动每个项目的位置,因此您最好复制整个数组。您可以采取一些措施来解决此瓶颈。第一是接受更少的数据点。用户屏幕的像素宽度小于要渲染的点数,因此,除非您的图形非常密集且包含很多行,否则您可能已经在视觉上摆脱了更少的数据点。

    问题仍然存在,因此您将不得不做更多的技巧。您可能要做的就是找到一种向图表库提供索引的方法,您可以仅追加数组并告诉图表仅从等于追加到数组的项目数量的索引开始进行渲染。图表仍然必须重新绘制每个点,但我们到了。

    最好的解决方案是跳过最后一个技巧,找到一个图表库,该图表库能够即时渲染新点,或者在给定新点数组差异时仅渲染新点,并将这些新点渲染为因此,旧积分的权利不退还其余积分。为了使它直观地显示您想要的内容,您必须将图表放入水平滚动 View ,然后禁用滚动并将其粘贴在右侧。不过,您将必须自己创建图例和指标。

    希望有人为您提供更好的解决方案哈哈哈,祝您好运。

    关于javascript - 如何在React中使用可变数据和实时图表实现最佳性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49053197/

    相关文章:

    Javascript 数组索引基础

    javascript - 由于上下文中未使用的属性,组件重新呈现

    javascript - 扩展 <选项>

    javascript - 跨页面均匀动态地拆分文本

    javascript - FlatList 不滚动

    javascript - 如何在标题和图标之间添加空格? react 中

    php - 为 highcharts 实时数据添加一个额外的点

    javascript - Highcharts:使用类别时 x 轴不一致

    javascript - Highstocks - 悬停在一个点上时显示年份

    javascript - 使用 XMLHTTPRequest 进行身份验证