如何利用React中的可变数据和实时图表实现最佳性能?

问题描述 投票:1回答:1

在过去的几周里,我使用不同的图表库(特别是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分,这个百分比看起来也有点太多了,尽管动画被禁用了。

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

很长一段时间,它让我觉得处理图表的反应方式是将数据作为道具传递。到目前为止还不错。我的问题是,这个数据道具只会被react.render识别为“已更改”并因此被重新渲染 - 如果您复制整个数据点阵列。这适用于小型数组,但不适用于数千个对象。

我试图在这里制作一个回购展示:

ChartJs(react-way)版本: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的渲染函数。

我原本以为这会更快,因为我们“更接近金属”并直接改变图表数据,但我看到使用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降低到100ms(第103行)并将第90行的maxSize设置为Sensor(2000)并在任务管理器打开的情况下运行,并关闭所有其他选项卡并监视cpu使用情况铬。正如您所看到的那样,当我们接近2000个数据点时,我们的cpu利用率接近60%。再次 - 这是没有动画。通过动画,它从40左右开始并从那里上升。

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

cpu每秒钟在画布中移动点是否有多大功能,或者我做错了什么?您是否知道其他任何图表库可以处理每秒数千点的实时图表?您通常如何处理可变数据点数组(来自MobX或其他)并在React中的图表中呈现它?与React一起寻找更多“裸机”电源“离网”时要遵循的任何良好做法。除了使用ref或好的模式之外还有其他方式吗?

编辑:

虽然我没有对它们进行测试,但从它的外观来看,下面的图表看起来比我到目前为止遇到的其他图表库要好得多。

我现在要测试它们,并在我试用它们后更新。

javascript reactjs highcharts chart.js mobx
1个回答
0
投票

每次移动数组时,您都需要移动每个项目的位置,因此您可以复制整个数组。您可以采取一些措施来解决这个瓶颈问题。第一是接受更少的数据点。您的用户屏幕的像素宽度要比要渲染的点的数量少,因此,除非您有一个包含大量线条的非常密集的图形,否则您可能已经在视觉上获得了更少的数据点。

问题仍然存在,但你将不得不做更多的诡计。您可以做的就是找到一种方法来为图表库提供索引,这样您就可以只追加数组并告诉图表只从索引处开始渲染,该索引等于附加到数组的项目数量。图表仍然需要重新报道每一点,但我们已经到了那里。

最好的解决方案是跳过最后一个技巧并找到一个图表库,它能够动态渲染新点,或者当给定一个新的点数组时将其差异化以仅渲染新的点并将这些新点渲染到因此,旧点的权利没有重新考虑其余的要点。为了让它看起来你想要什么,你必须将图表放入水平滚动视图,然后禁用滚动并保持粘在右边。您必须自己制作图例和指标。

希望有人有更好的解决方案哈哈哈祝你好运。

© www.soinside.com 2019 - 2024. All rights reserved.