JS网格性能对比

JS grid performance comparison

我正在使用 angular-ui-网格 (http://ui-grid.info/) to display tabular data. On the whole, it was quite slow and so we decided to use ag-grid (https://www.ag-grid.com/)。这对于处理常规大小的数据集来说性能更高,也更好。

但是,现在我们正在处理一些大小为 100 列 x 10,000 行(约 100 万个单元格)的表格数据,并且网格的性能似乎 quite 很慢。

我想知道是否有人使用过 hypergrid (https://fin-hypergrid.github.io/core/2.0.2/) -- 似乎 'solve' 大列 x 大行的问题在他们的演示中似乎快得多(几乎是数量级)在大型数据集上。

hypergrid compare to ag-grid or react-virtualized 在大数据量上的表现如何?

我没有尝试过您提到的任何示例库,但也许我可以解释为什么 fin-hypergrid 最突出。我的意见主要基于我的 JavaScript 知识以及这类东西在后台的工作原理。

我应该从 react-virtualizedag-grid:

开始
  • 两者都使用填充 DOM 的方式,只在视图中显示一部分数据,动态地从 DOM 中删除不再可见的内容,并将即将到来的内容添加到进步。现在这里的问题在于在 DOM 中添加和删除内容,因为这往往执行得非常快/每秒多次。因此,我们会遇到一些滞后或抖动。您实际上可以检查 Web 控制台 > 配置文件 > 记录 JavaScript CPU 配置文件 并查看此方法需要时间才能完成。因此,与 react-virtualizedag-grid 唯一不同的是它们以最平滑的方式应用这些更改的算法。

ag-grid,据我所知,是受此问题影响最大的一个,因为您实际上可以看到一些尚未完成渲染的元素,并且当您滚动得太快时会遇到严重的延迟.

另一方面,

react-virtualized 在以最流畅的方式实施其算法方面做得非常出色。这可能是 DOM 操作类别中可用的最佳库,尽管它仍然存在操作 DOM 速度过快导致延迟的问题,尽管这仅在涉及大块数据时才会出现。

以下是 fin-hypergrid 出色的原因:

  • fin-hypergrid 的最大优点是它根本不执行 DOM 操作,因此您已经避免了由于使用 [=19] 过快添加和删除东西而引起的问题=]
  • fin-hypergrid 也仅显示用户看到的数据并动态删除不可见的内容。它还提前添加以实现平滑的滚动感,因此不会显示静止渲染的项目。
  • fin-hypergrid 他们的滚动算法也做得非常好,以获得最平滑的方式,因此没有抖动或滞后。

这并不意味着 hypergrid 就很好,它也有一些缺点:

  • 由于 fin-hypergrid 是用 HTML5 Canvas 制作的,因此样式设置将变得非常痛苦,因为它不接受 CSS。您需要手动设置样式。
  • 需要记住的几件事是表单控件,例如 <select>、单选按钮、复选框等,实施起来真的很痛苦。如果您正在尝试实施类似的操作,请谨慎行事。
  • 主要用于显示数据,简单的列编辑,不涉及文本框以外的任何内容,实现最流畅的滚动感。

现在总而言之,我可能会建议使用 react-virtualized,因为它提供了比 fin-hypergrid 更流畅的滚动。如果你愿意忽略fin-hypergrid的缺点,那么fin-hypergrid是最好的选择。

更新:

自从我们讨论了 JS / CSS、canvas 这些 table 的实现。我应该提到最后一个可能的竞争者,尽管这个主要不是 js table 库,而是一个可能使用了 Google Sheets 的框架,它被称为 d3.js.

  • d3.js拥有canvas的速度和威力,同时保留了HTML的结构,也就是说可以用CSS来设计风格!
  • 它最大限度地利用了HTML 5 SVG
  • 我在d3.js
  • 中说得再好不过了

在此讨论中 d3.js 的唯一缺点是:

  • 没有可用的好 table 库使用 d3.jsGoogle Sheets 即。但是他们不共享代码。
  • d3.js 很难学,尽管有很多东西可以帮助我们更快但不是那么快地学习。

如果您想要 Canvas 的速度和 CSS 样式功能,那么 d3.js 是学习它的关键问题。

我使用免费版的 handsontable 来处理大数据集。 请参阅包含 10000*100 个单元格的示例 - http://jsfiddle.net/handsoncode/Lp4qn55v/

例如,对于 angular 1.5:

<hot-table class="hot handsontable htRowHeaders htColumnHeaders" settings="settings"
                       row-headers="rowHeaders"  datarows="dba">
    <hot-column ng-repeat="column in Value" data="{{column.COL1}}" >
    </hot-column>
</hot-table>

查看文档 here

您是否考虑过使用为大型数据集设计的东西?

Clusterize.js

我相信它的工作方式是它只加载您正在查看的元素数据。因此浏览器不会滞后,因为它具有显示视口所需的元素。

演示页面加载了 3 个示例,每个示例包含 500,000 个元素(总共 1,500,000 个元素)。

更新 - 带有示例代码段

  • 因为我没有要加载的 100,000 x 200 数据元素,所以我使用 JavaScript.
  • 构建了 100 x 200
  • 然后我复制那个数组并将其插入数据数组 1000 次。
  • 这样我就可以在不使 JavaScript 引擎过载的情况下达到您的总数据集大小。
  • 因为很难判断它是否真的执行了 100,000 行,所以我调用了显示在输出顶部的 getRowsAmount() 函数。
  • 您可能需要根据您的视口调整块大小和簇大小,但这应该表明该库完全有可能满足您的需求。

$(function() {
  var dataBlock = []
  var data = [];
  const rows = 100000
  const cols = 200;
  const blockSize = 100;
  const blocks = rows / blockSize;

  for (let i = 0; i < cols; i++) {
    $("thead tr").append(`<th>C${i}</td>`);
  }

  for (let j = 0; j < blockSize ; j++) {
    var tr = $("<tr />");
    for (var i = 0; i < cols; i++) {
      tr.append(`<td>R${j}-C${i}</td>`);
    }

    dataBlock.push($("<div />").append(tr).html());
  }

  for (let i = 0; i < blocks; i++) {
    $.merge(data, dataBlock);
  }

  var clusterize = new Clusterize({
    rows: data,
    scrollId: 'scrollArea',
    contentId: 'contentArea',
    rows_in_block: 10,
    blocks_in_cluster: 2,
  });
  
  $("#totalRows").text(clusterize.getRowsAmount());
});
table td {
  white-space: nowrap;
  padding: 0 5px;
}
<html>

<head>
  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
  <link href="https://clusterize.js.org/css/clusterize.css" rel="stylesheet" />

  <script src="https://clusterize.js.org/js/clusterize.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>

<body>
  Total Rows: <span id="totalRows"></span>
  <div class="clusterize">
    <div id="scrollArea" class="clusterize-scroll">
      <table class="table">
        <thead>
          <tr></tr>
        </thead>
        <tbody id="contentArea" class="clusterize-content">
          <tr class="clusterize-no-data">
            <td>Loading data…</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</body>

</html>

The library supports appending data so with your large data sets your may want to load some of your data through AJAX.

我浏览了不同的数据网格选项。然后我找到了this.

希望此回答对正在寻找数据网格之间的性能比较的任何人有所帮助。

这里有几点需要注意,即使你看过我提供的文章。

1 - Once a grid is 'fast enough', which means the rendering lag is not noticeable, then it doesn't matter which grid is faster than the next.

2 - A canvas based grid is not a HTML grid - you cannot customise it with HTML. The grid will struggle to be styled / themed / customised by the standard JavaScript / CSS developer.

选择你的毒药,因为当涉及到消费者层面时,这不仅仅是性能。