11

I was using angular-ui-grid (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/). This was much more performant and better to deal with for regular-sized data-sets.

However, now we are working with some tabular data of the size of 100 cols x 10,000 rows (~1M cells) and the grid seems quite slow in performance.

I was wondering if anyone had used hypergrid (https://fin-hypergrid.github.io/core/2.0.2/) -- it seems to 'solve' the issue of large cols x large rows and in their demo it seems much faster (almost by an order of magnitude) on large data sets.

How does hypergrid compare to ag-grid or react-virtualized in performance on large data sizes?

David542
  • 104,438
  • 178
  • 489
  • 842
  • Creating ~10e5 DOM nodes? I suspect *everything* will be slow. – Jared Smith Aug 28 '17 at 00:44
  • @JaredSmith hypergrid uses canvas though. – David542 Aug 28 '17 at 01:54
  • I don't know about the others you're mentioning. Haven't used them. react-virtualized would be worth looking into though since it only creates enough views to fill the visible rows/columns at a given time. It can easily handle hundreds of thousands of rows and/or columns. – bvaughn Aug 28 '17 at 02:58
  • The recent release of v13 of ag-grid includes a number of performance improvements - it might be worth taking a look at the demo now: https://www.ag-grid.com/example.php The grid does use virtualization (both row and column), so should be pretty snappy – Sean Landsman Aug 28 '17 at 08:10
  • @SeanLandsman vertical scroll seems acceptable. Horizontal scroll seems choppy as hell to me, and that's only with 22 cols. Why is the horizontal scroll so lousy compared to vertical scroll with ag-grid? – David542 Aug 29 '17 at 20:33
  • I suppose, that they drew on attention to vertical rendering, but not to horizontal. If you try to look on example and see in html elements developer tool what they do, when scrolling - they rerender header. For example, in handsontable it is only change values inside span element. – egorlitvinenko Sep 01 '17 at 12:48
  • @David542 My answer now shows 100,000 x 200 data set with no lag when scrolling. Let me know if that works for you? – fjoe Sep 06 '17 at 20:36

4 Answers4

8

I haven't tried any of those example libraries you mentioned, but perhaps I could explain why fin-hypergrid stands out the most. My opinion is primarily based on my JavaScript knowledge and how this kind of stuff works in the back.

I should probably start with react-virtualized and ag-grid:

  • Both use the way of populating the DOM and only displaying a portion of data to the view, dynamically removing things from the DOM that aren't visible anymore and adding the upcoming things in advance. Now the problem here lies in adding and removing things in the DOM since this tends to be executed really fast / multiple times a second. Because of this we experience some lag or jitter. You can actually check Web Console > Profiles > Record JavaScript CPU Profiles and see that this method takes time to complete. So the only thing that differs from react-virtualized and ag-grid are their algorithms of applying these changes in the smoothest possible manner.

ag-grid, from what I can see, is the one that suffers the most from this issue as you could actually see some elements that haven't finished rendering yet and experience severe lag when you scroll too fast.

react-virtualized on the other hand does a splendid job implementing its algorithm in the smoothest possible manner. This might be the best library available in the DOM manipulation category though it still suffers from the problem of manipulating the DOM too fast which creates lag, though this is only seen when large chunks of data are involved.

Here are the reasons why fin-hypergrid excels:

  • The best asset of fin-hypergrid is it doesn't perform DOM manipulation at all so you are already saved from the problem caused by adding and removing things too fast since it uses <canvas>
  • fin-hypergrid also displays only data that the user sees and dynamically removes things that aren't visible. It also adds in advance to achieve a smooth scroll feeling, so no still-rendering items are shown.
  • fin-hypergrid also does a really great job on their scrolling algorithm to attain the smoothest possible manner, so there is no jitter or lag.

Now that doesn't mean that hypergrid is all good, it has some disadvantages too:

  • Since fin-hypergrid is made with HTML5 Canvas, styling it will become a real pain as it doesn't accept CSS. You would need to style it manually.
  • A few things to keep in mind are form controls such as <select>, radio buttons, checkboxes, etc. would be a real pain to implement. If you are trying to implement something like this then proceed with caution.
  • It's primarily used for displaying data with simple column edits, not involving anything other than a textbox, and achieving the most smooth scroll feeling.

Now in conclusion, I would probably suggest using react-virtualized instead since it offers the smoothest scroll, above fin-hypergrid. If you are willing to disregard the downsides of fin-hypergrid, then fin-hypergrid is the best option.

UPDATED:

Since we discussed JS / CSS, canvas implementations of these tables. I should have mentioned the last possible contender though this one is not primarily a js table library but a framework in which Google Sheets might have been used it is called d3.js.

  • d3.js has the speed and power of canvas and at the same time retains HTML structure, this means that it is possible to style it with CSS!
  • It maximizes the usage of HTML 5 SVG
  • I can't say anything more better in d3.js

The only downsides of d3.js in this discussion is that:

  • There is no available good table libraries out there that uses d3.js. Google Sheets that is. But they do not share code.
  • d3.js is just very hard to learn, though there are lots of stuff out there that helps us learn this faster but not that fast.

If you wanted speed of Canvas with CSS styling capabalities then d3.js is the key the problem is learning it.

masterpreenz
  • 2,280
  • 1
  • 13
  • 21
  • thanks for this answer: how do you style `canvas` elements? Could you show me an example? – David542 Sep 01 '17 at 21:55
  • The only way to style elements in a `canvas` is to dig in `javascript`. In their example demo file called `index.js: this is where hypergrid gets initialized and custom behaviors added` in the part where `grid.behavior.dataModel.getCell` was initialized, here you can modify the styling behavior on each cell in the grid. Just take note that `CSS` properties do not apply in canvas, the only thing you can achieve here are `changing font, font sizes, fillColor, foreColor` and other canvas stuff it can offer http://www.html5canvastutorials.com/ – masterpreenz Sep 01 '17 at 23:12
  • how does Google Sheets do its styling then? Is there a javascript file or something that you can view in the browser to see all the style that's added to the sheet? How would I view that? – David542 Sep 04 '17 at 06:01
  • Google Sheets are just html / javascript / css implementation it's not a canvas, it's almost the same with `react-virtualized` though Google Sheets perfected the algorithm to not have lag spikes at all and they don't share their code as well which is a bad. If you mean the javascript file for `hypergrid` that does the styling? `index.js -> the line where this can be found grid.behavior.dataModel.getCell = `. – masterpreenz Sep 04 '17 at 06:21
  • @David542 though I forgot to mention another one which Google Sheets was made. Since I mentioned HTML / CSS / JS implementation, canvas, there is also another contender called (d3.js)[https://d3js.org/]. I think I should just simply update my answer – masterpreenz Sep 04 '17 at 06:31
  • It might be both as there is no way we can put HTML elements in a canvas, the cell divs are actually present `same as react-virtualized` is done. _I just discovered it's actually both. The text's was rendered in `` while the elements was rendered in `d3.js`_ – masterpreenz Sep 04 '17 at 23:26
  • thanks for the update. How do you know that Google Sheets uses d3.js? Do they use d3.js AND canvas -- or does d3.js REPLACE canvas? If you could add a bit more details on how you discovered that, that'd be great. – David542 Sep 05 '17 at 21:27
  • also, in searching the Google Sheets html (developer console), I do see a canvas tag but I don't see anything for `d3.js`. How do you know it's using that? – David542 Sep 05 '17 at 22:24
  • 1
    It's not actually replacing `` if you might have checked the only things that are rendered in `` was `text, cells along with their, fillColor, foreColor, borders and alignments which is all available in canvas`. The others `scrollbars / selection tool / etc.` are made with JS. _How do they do their styling then?_ It's very hard to explain by words it's like `data = [ { x: 1, y: 2, value: "this is a cell", color: "#ccc", backgroundcolor: "#fff", font: "etc."} ]` and this cell data is interpreted by a complex drawing algo in JS that applies this to `` – masterpreenz Sep 06 '17 at 00:40
  • 1
    You are right that being pure canvas Hypergrid is faster than Dom-based equivalents. But you need to be aware of the huge limitations that canvas based grids offer - many other filtering, sorting, editing, styling behaviours that users expect with their grid are much harder in Hypergrid than other grids. they are possible but harder and sometimes the improvement in performance in speed that you might not need is not worth the trade-off in poorer functionality. – Jonny Wolfson Aug 21 '19 at 16:55
6

I have gone through different data grid options. Then I found this.

Hope this answer helps to anyone who is looking for performance comparison between data grids.

Few points to be noted here, even you have gone through with the article I provided.

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.

Pick your poison because it is not just the performance when it comes to the consumer level.

Community
  • 1
  • 1
ymssa___
  • 993
  • 9
  • 16
  • 2
    I could not agree more. We produce the Adaptable Blotter that sits on top of lots of HTML5 DataGrids both canvas and Dom-based. And we invariably find that the performance requirements are not actually needed in real life (as most of the time they dont actually have 250,000 rows all updating 250 times a second) and that by going for performance with canvas they end up with an inferior user experience for the things they actually do on a daily basis - styling, sorting, filtering, editing etc. Performance is important but be realistic. – Jonny Wolfson Aug 21 '19 at 16:58
  • 2
    Exactly the point! it is really based on what you want most with your application. If rendering speed is not noticeable and you can also do styling, add dom objects as well then its the best I think, as you said realistic. – ymssa___ Aug 22 '19 at 12:33
  • 2
    yep. In fact IMHO its simpler than that. We do hundreds of demos a year so we see lots and lots of grids and grid set ups, and I would say that 95% of the time its clear that they need a DOM, not a canvas grid. And in fact ag-Grid is now so way out as the best HTML5 DataGrid on the market, 95% of the time the Dom-based DataGrid they need is ag-Grid. I cannot recall the last time we advised a client to use anything other than ag-Grid - its market leader for a reason. – Jonny Wolfson Aug 23 '19 at 07:29
  • Yes, right now we are using Ag-Grid as well. I've also implemented the fin-hypergrid ver. 3.2.0 but its too hard to get the html components get going. With Ag-Grid I have only highlighting problem to get fixed. :D – ymssa___ Aug 24 '19 at 19:32
3

Have you considered using something designed for large data sets?

Clusterize.js

I believe the way it works is it only loads the elements data for the ones you are looking at. Therefore the browser doesn't lag because it has the elements need to display the viewport.

The demo page loads 3 examples with 500,000 elements each (1,500,000 total elements).

Update - With Example Snippet

  • Because I do not have 100,000 x 200 elements of data to load I build 100 x 200 using JavaScript.
  • Then I copy that array and insert it into the data array 1000 times.
  • This way I can reach your total data set size without overloading the JavaScript engine.
  • Since it is hard to tell that it is really doing 100,000 rows I called the getRowsAmount() function which is displayed at the top of the output.
  • You may need to play with the block & cluster sizes based on your viewport but this should show you that this library is totally possible of supporting your needs.

$(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.

fjoe
  • 1,150
  • 7
  • 15
  • how is that different than ag-grid or react-virtualized. Both of those exhibit smooth vertical scroll. How about with 200 columns and 100,000 rows? Two columns seems quite trivial to demonstrate. – David542 Sep 04 '17 at 05:44
  • @David542 I have added an example with 10,000 x 50 but was able to run without issue locally 10,000 x 200. The hard part is creating all of the data for the tool to use. Maybe grab my code give it a try with your data and let us know? – fjoe Sep 04 '17 at 07:18
  • @David542 I was able to figure out a way to build all of the fake data you need and over load the JavaScript engine. If you would like to see what I had before you can always check the last revision of the answer. This example now shows 100,000 x 200 table elements. – fjoe Sep 04 '17 at 07:52
1

I used free version of handsontable for big datasets. See example with 10000*100 cells - http://jsfiddle.net/handsoncode/Lp4qn55v/

For example, for 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>

See documentation here

egorlitvinenko
  • 2,736
  • 2
  • 16
  • 36