实时数据绘图性能HTML5画布与DOM添加的比较

5
我有一些实时数据:3个整数会随时间改变。这些整数来自我加速度计的读数:xyz。我正在思考一种绘制这些数据的方法,以便更容易地跟踪变化趋势。
有许多图表库可供选择,例如flot。我想将整数表示为柱形高度。有两种方法可以用来显示条形图:
1. 使用
标签创建条形,在父级
中追加它们。 2. 使用HTML5画布绘制条形,代表整数。
我的问题是:从性能的角度来看,假设数据更新频率为50毫秒(即每50毫秒数据将发生变化),这两种方法哪种效果更好?

我认为对于快速实时操作,重复使用相同的条形图比重新绘制整个图表更有效率,但是现在Canvas也越来越多地得到GPU的帮助... - dandavis
@dandavis 我不关心 GPU,我关心 CPU,并且我会添加新的条形图,我不会使用相同的条形图,每当整数发生变化时,都会添加一个新的条形图。 - ProllyGeek
如果每次添加一个新的条形图,您必须使用画布:如果添加数万个条形图,DOM 最终会崩溃。我想更多地展示它们的全屏宽度,比如 100,然后只需将高度向下移动一个,右侧为新值,左侧为旧值丢弃。这可能比每次重新绘制光栅图要快得多,而您需要做的就是在循环中调整每个条形图的高度... - dandavis
使用分页技术和模板,可以将过去的内容存储在“json”中,而不是HTML,以实现最大/无限容量。 - dandavis
好的编辑。 这个问题好多了。 - bjb568
显示剩余2条评论
5个回答

6
在一定程度上,这取决于几个因素:
  • 您需要更新的项目数量(您是在讨论10个、100个、1000个还是更多)
  • 您想要更新的频率将是一个重要因素,您受限于浏览器执行JavaScript的速度。
  • 浏览器-某些浏览器可以以显着不同的速度呈现内容。
一个很好的比较例子是查看一些D3性能比较。因为核心库在底层做着相同的工作,所以这比较了SVG(基于DOM)和Canvas渲染之间的渲染速度。首先看一下这两个群集示例: 如果您开始增加频率和项目数,Canvas将优于SVG,因为它对浏览器来说是一个更轻松的工作量。它不必以相同的方式操作DOM,检查CSS规则等。然而,由于这些原因,SVG更加强大。

这篇D3 Google群组中的文章对性能进行了很好的分析,比较了浏览器渲染时间。以下是一些数字示例(尽管这些数字有点旧):

  • Chrome在SVG上的渲染速度比Canvas慢74倍。
  • Firefox在SVG上的渲染速度比Canvas慢150倍。
  • Opera在SVG上非常快,但在Canvas上的渲染速度比SVG慢71倍。

2
@ProllyGeek 希望这对你有所帮助。如果你觉得值得的话,别忘了颁发悬赏,否则这些点数就会消失在虚空中。 - Ian
1
只是一个快速的提示,如果你正在处理大量的粒子/元素...或者将以高帧率重新渲染它们,那么请使用画布(canvas),SVG不会很好地缩放。我已经花了整个早上进行测试并得出结论。 - jadinerky
你介意贴一个基准测试的例子给未来的用户吗?这将非常有帮助。 - Fyre
@Fyre,展示了两个FPS示例。 - Ian

1
这里有一个fiddle,展示了flot柱状图和DOM/div方法。您可以单独运行它们或一起运行,并使用任务管理器比较外观和cpu负载。
这是基于我对此问题的回答(为图表提供了“Windows 7任务管理器”样式)。
两种方法的更新循环:
function update() {
    GetData();
    $.plot($("#placeholder"), dataset, options)
    timerFlot = setTimeout(update, updateInterval);
}

function updateDom() {
    GetData();
    $('#domtest').html('');
    for (var i = 0; i < data.length && i < 100; i++) {
        $('#domtest').append('<div class="bar" style="height: ' + (3 * data[i][3]).toString() + 'px; top: ' + (300 - 3 * data[i][4]).toString() + 'px;"></div>');
    }
    timerDom = setTimeout(updateDom, updateInterval);
}

如果这个答案能够提供一个可视化的性能比较,比如帧率(FPS),那就更完美了。但即便如此,这仍然是一个非常棒的答案,非常感谢。 - ProllyGeek

0

我建议使用d3和一个补充的图表库来绘制你的条形图。然后,你可以使用SVG,它比追加DOM节点更高效。我建议看一下c3


谢谢回答,但我建议提供一个带有基准测试证明的答案。 - ProllyGeek

0

我同意Sean关于D3的回答。将其与jQuery或D3的本地json处理相结合,您可以快速提取数据。例如,我编写了代码来提取LDAP查询数据,记录编号为1000多条,周转时间约为一秒钟。但这是服务器端。

在渲染方面,请参阅这些示例,比较画布和SVG渲染性能之间的差异。这不是基准测试,但您可以很清楚地看到性能不是问题。

bl.ocks.org/mbostock/1276463 - bl.ocks.org/mbostock/1062544 - bl.ocks.org/mbostock/9539958

但是对于您关于图表的问题,D3非常优雅地处理数据更新与数据连接。这是一篇关于随时间更新数据系列的好文章。bost.ocks.org/mike/path/

希望这有所帮助。


0
我建议采用Canvas方法。
更改Dom元素会导致DOM重绘调用以在屏幕上绘制元素。在您的情况下,有3个元素将经常更改。
动画的内部操作将按以下方式完成: 将高度为x的元素更改为x + 3。 第一步,浏览器将元素的高度更改为+1,重新绘制并调整其中的所有子元素。然后增加+1并重新绘制和调整子元素,依此类推。每次更改元素时,浏览器内部都会发生很多事情。
谈到画布:它就像一个绘画板,无论您增加或减少多少周期,画布都不会进行任何迭代式的绘制调用。
希望这提供了一些信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接