Framework: 8.1 Grid is much slower than table

Created on 21 Oct 2017  路  22Comments  路  Source: vaadin/framework

Opening a new ticket for this, as the original is closed. Please read all the comments there https://github.com/vaadin/framework/issues/8678.

Using v8.1.15

The grid is slower than the table for when using a larger number of columns (10+). Tested with 80 columns, with 10 rows, the grid loading takes over 10 seconds, the table loads in 1-2 seconds.

bug

Most helpful comment

Grid is not only slow with many columns, but with components. I have a grid with about 200 rows that has two columns where one contains a Link:

grid.addComponentColumn(item -> {
  Link link = new Link(item.getNummer(), new ExternalResource("#!detailView/" + item.getId()));
  return link;
}).setCaption("Show Details");

That kills performance already. When I drag the scrollbar, there is a lag of 1 second ca. every 50 rows. I cannot present that to users. It would be more acceptable to load the whole table at once waiting a little longer and then scroll without "stuttering". I'm deeply missing the setPageLength(0) of the old table. I had no success with the CacheStrategyExtension of the GridExtensionPack Add-on. It seems to have no effect.

Edit: Workaround for my problem: Instead of a component add a column with HtmlRenderer that creates a simple link:

grid.addColumn(item ->
"<a class='v-link' href='#!detailView/" + item.getId() + "'>" + item.getNummer() + "</a>",
  new HtmlRenderer())
  .setCaption("Show Details");

All 22 comments

This is actually duplicate to https://github.com/vaadin/framework/issues/8216 not #8678 which was about specific rendering issue due regression, i.e. Vaadin 8 Grid being slower than Vaadin 7 Grid, which was fixed.

There are still some performance regressions between the FW 7 and FW 8 versions of the Grid. Some have been fixed but there still are issues left.

Even with after the regressions fixed, I would still want to remind you that Grid does not support lazy loading column data nor does it recycle the elements in DOM for columns. Thus it is not really meant for showing _a lot of columns_ to the user. For that we have the Spreadsheet add-on.

Also, I would be like to know what the use case for showing 80 columns at once to the users is ? Is the UX still good, in terms that they need to see all and can interpret the data properly?

Thanks for looking at it. The 80 columns is just an example to showcase the differences in loading times. I have a use case with ~25 columns, which is slow too.

Use case example:

image

  1. For every column we have a filter in the header. It's an enterprise application, so the user wants to have those filters for everything. Sometimes it filters by user, sometimes by country etc, etc.
  2. We use a grid exporter addon to export to excel/csv, which requires those columns to be in the grid (not really important, since we could rewrite it)

25 columns is probably something that should not be too slow, but with the way the Grid works, we might not be able to make super fast without major rewrite, which we are probably not going to do. But, it should definitely not be slower than in V7 however. And preferably also as-fast or faster than old Table.

grids.zip

Please check this example (rewrite the column number to 25 instead of 80)

This is weird considering that the major selling factor for Grid (and the introduction of renderers in place of plain components in cells) was that Grid was supposed to render much faster. Now, the goal suddenly becomes to make it "as fast as Table"? I don't see the gains here - Table had a much easier API, wrapping everything with Renderers requires effort and now it turns out that it might not even be faster?

Plus, I really don't like this mention of "this component doesn't do what you want quickly enough, but we have this paid component here that fulfills this purpose". Regardless of the intentions, this is a worrying remark.

@Pwilkin sorry for not being clear enough, I was referring to having lots of columns in both grid and table. Neither component supports _infinite columns_. Grid with 25 columns should not be slower than Table, that it is the starting point. And I suggested Spreadsheet only for the case of having _infinite columns_.

Grid is a lot faster than Table when you have lots of components in cells, because of renderers. Grid is also faster in many basic operations. If that is not a case, it is a regression. Unfortunately we have had some performance issues with some changes made to Grid in 8.0. Several have been fixed already, but apparently some are still there, like with having lots of columns.

Since 8.1 Grid also has ComponentRenderer which allows to have any component in any cell, like with Table. The API is not exactly the same though. There the performance might not be as good as with "proper renderers", but it should not be worse than Table either.

I've built a page with 20 tables with 4 columns each and have run into similar performance problems mentioned here. The browser locks up while calculating column widths even though I use a fixed size table with fixed size widths. Aren't there some optimizations that can be made here?

We are also affected by Vaadin 8.1 not loading the Grid as fast as we wished or used to in Vaadin 7.
A default grid that is shown in the application is 3000 rows with 30 columns (including 10 hidden columns)
We have not looked at the Spreadsheet Addon yet ... and were also hoping that the several grid performance fixes in V8 would take care of the issue.
Added a performance test suite here: https://github.com/FOCONIS/slow-grid-sample

We have exactly the same problem. Grid becomes very slow with large number of columns.

We have also gotten some feedback regarding slow processing time for views which utilize the Grid with 8-20 columns.

Same Views worked with v7 Tables without problems.

Had a stab at this and it seems it is caused when by an extra call to calculate() from the AutoColumnWidthsRecalculator (and there ending up in applyColumnWidthsWithExpansion()) - this is done immediately instead of being _scheduled finally_ like in V7, because both the header & footer are not dirty at that point in V8, but the footer is dirty in V7 and thus the calculation is first _scheduled finally_. This was changed recently in https://github.com/vaadin/framework/commit/165fcb77d1e3ba1612ea921aa9313a54f547716a, but there are other things here at play too, and need to continue the investigation.

The slowness is pinned to awful lot of calls to ComputedStyle when calculating the column widths due to not having defined widths. The performance is much better after setting column width to e.g. _200px_.

There should preferably be only one column width calculation, done at a suitable time, and in a sensible way, the usage of ComputedStyle here and attaching extra elments and doing measurements is a very costly operation here, and having more columns increases the amount calculations for each column. This should be optimizable.

Thanks for the tip, @pleku. I set all of the columns to fixed widths and wait time was cut approximately in half.

In our slow grid generation demo: https://github.com/FOCONIS/slow-grid-sample we have set the column width already to fixed values to eliminate that part of the problem:
https://github.com/FOCONIS/slow-grid-sample/blob/e54d1eb7ee61d68de9503e68e3a013832ac6c374/src/main/java/com/sample/slowgrid/MyUI.java#L155
Still the time to generate the grid is always above the problematic delay of 1s for usable page rendering times.

Okay, so I did a client-side debug on the nice sample provided by @focbenz

Out of the entire rendering process, the heaviest one currently is setHidden in ColumnConnector. Reportedly, this should not trigger if the visibility hasn't changed, so it seems like either (a) there's something weird going on here or (b) the column inserting code is horribly heavy. Maybe columns should be rendered all at once during the initial render instead of inserting them one-by-one?

Here's some data:

1749.5聽ms100.00聽% | 1749.5聽ms100.00聽% | com_vaadin_client_widgets_Escalator$BodyRowContainerImpl_$getHeightOfSection__Lcom_vaadin_client_widgets_Escalator$BodyRowContainerImpl_2Dcom.sample.slow鈥id-0.js:64532 | 聽
-- | -- | -- | --
1611.3聽ms92.10聽% | 1611.3聽ms92.10聽% | com_vaadin_client_widgets_Escalator$BodyRowContainerImpl_$getMaxVisibleRowCount__Lcom_vaadin_client_widgets_Escalator$BodyRowContainerImpl_2Icom.sample.slow鈥id-0.js:64547 | 聽
1579.2聽ms90.27聽% | 1579.2聽ms90.27聽% | com_vaadin_client_widgets_Escalator$BodyRowContainerImpl_$verifyEscalatorCount__Lcom_vaadin_client_widgets_Escalator$BodyRowContainerImpl_2Vcom.sample.slow鈥id-0.js:64858 | 聽
1417.5聽ms81.03聽% | 1417.5聽ms81.03聽% | com_vaadin_client_widgets_Escalator$ColumnConfigurationImpl_$removeColumns__Lcom_vaadin_client_widgets_Escalator$ColumnConfigurationImpl_2IIVcom.sample.slow鈥id-0.js:65306 | 聽
1416.5聽ms80.97聽% | 1416.5聽ms80.97聽% | com_vaadin_client_widgets_Grid$Column_$setHidden__Lcom_vaadin_client_widgets_Grid$Column_2ZZVcom.sample.slow鈥id-0.js:23400 | 聽
1416.5聽ms80.97聽% | 1416.5聽ms80.97聽% | com_vaadin_client_widgets_Grid$Column_$setHidden__Lcom_vaadin_client_widgets_Grid$Column_2ZLcom_vaadin_client_widgets_Grid$Column_2com.sample.slow鈥id-0.js:23395 | 聽
1416.5聽ms80.97聽% | 1416.5聽ms80.97聽% | com_vaadin_client_connectors_grid_ColumnConnector_updateHidden__Vcom.sample.slow鈥id-0.js:23308 | 聽
1416.5聽ms80.97聽% | 1416.5聽ms80.97聽% | com_vaadin_client_metadata_ConnectorBundleLoaderImpl$1$1$245_jsniInvoke__Ljava_lang_Object_2Lcom_vaadin_client_JsArrayObject_2Ljava_lang_Object_2com.sample.slow鈥id-0.js:32402 | 聽
1416.5聽ms80.97聽% | 1416.5聽ms80.97聽% | com_vaadin_client_metadata_JsniInvoker_invoke__Ljava_lang_Object_2_3Ljava_lang_Object_2Ljava_lang_Object_2com.sample.slow鈥id-0.js:32337 | 聽
1416.5聽ms80.97聽% | 1416.5聽ms80.97聽% | com_vaadin_client_metadata_Method_$invoke__Lcom_vaadin_client_metadata_Method_2Ljava_lang_Object_2_3Ljava_lang_Object_2Vcom.sample.slow鈥id-0.js:36476 | 聽
1416.5聽ms80.97聽% | 1416.5聽ms80.97聽% | com_vaadin_client_metadata_OnStateChangeMethod_$invoke__Lcom_vaadin_client_metadata_OnStateChangeMethod_2Lcom_vaadin_client_communication_StateChangeEvent_2Vcom.sample.slow鈥id-0.js:36515 | 聽
1416.5聽ms80.97聽% | 1416.5聽ms80.97聽% | com_vaadin_client_ui_AbstractConnector_$onStateChanged__Lcom_vaadin_client_ui_AbstractConnector_2Lcom_vaadin_client_communication_StateChangeEvent_2Vcom.sample.slow鈥id-0.js:14337 | 聽
1416.5聽ms80.97聽% | 1416.5聽ms80.97聽% | com_vaadin_client_ui_AbstractConnector_onStateChanged__Lcom_vaadin_client_communication_StateChangeEvent_2Vcom.sample.slow鈥id-0.js:14457 | 聽
1416.5聽ms80.97聽% | 1416.5聽ms80.97聽% | com_vaadin_client_communication_StateChangeEvent_dispatch__Lcom_google_gwt_event_shared_EventHandler_2Vcom.sample.slow鈥id-0.js:20687 | 聽
1416.5聽ms80.97聽% | 1416.5聽ms80.97聽% | com_google_web_bindery_event_shared_SimpleEventBus_$doFire__Lcom_google_web_bindery_event_shared_SimpleEventBus_2Lcom_google_web_bindery_event_shared_Event_2Ljava_lang_Object_2Vcom.sample.slow鈥rid-0.js:4903 | 聽
1416.5聽ms80.97聽% | 1416.5聽ms80.97聽% | com_google_gwt_event_shared_HandlerManager_$fireEvent__Lcom_google_gwt_event_shared_HandlerManager_2Lcom_google_gwt_event_shared_GwtEvent_2Vcom.sample.slow鈥rid-0.js:4835 | 聽

|Browser|Vaadin Version|Grid Size (Visible Columns,Hidden Columns,Rows)|Render Time (ms)|Request Time (ms)|
|-------|--------------|------------------|----------------|-----------------|
|CH|8.1.6|(100, 0, 1000)|3260|53|
|CH|8.1.6|(50, 50, 1000)|7259|27|
|FF|8.1.6|(100, 0, 1000)|7275|33|
|FF|8.1.6|(50, 50, 1000)|12913|30|
|IE|8.1.6|(100, 0, 1000)|11383|92|
|IE|8.1.6|(50, 50, 1000)|20233|38|

Rendering times for 100 visible columns significantly lower than for 50 hidden and 50 visible columns. Request Time as expected is less.

10465 should help for the case where there are initially hidden columns

10465 is available in 8.2.1 and fixes the problem with the initially hidden columns.

|Browser|Vaadin Version|Grid Size (C,HC,R)|Render Time (ms)|Request Time (ms)|
|-------|--------------|------------------|----------------|-----------------|
|CH|8.2.1|(100, 0, 1000)|2869|66|
|CH|8.2.1|(50, 50, 1000)|2011|34|
|FF|8.2.1|(100, 0, 1000)|6507|28|
|FF|8.2.1|(50, 50, 1000)|4956|30|
|IE|8.2.1|(100, 0, 1000)|10470|79|
|IE|8.2.1|(50, 50, 1000)|7186|88|

Is there any possibility to also speed up the first time rendering of the grid?

Can you test out what kind of results you get with my patch in #10579 ? It should improve the initial render by <insert some vague description here>.

Patch tested and it helps to bring down the initial rendering time for all browsers:

|Browser|Vaadin Version|Grid Size (C,HC,R)|Render Time (ms)|Request Time (ms)|
|-------|--------------|------------------|----------------|-----------------|
|CH|8.4-SNAPSHOT|(100, 0, 1000)|2535|68|
|CH|8.4-SNAPSHOT|(50, 50, 1000)|1782|38|
|FF|8.4-SNAPSHOT|(100, 0, 1000)|4998|26|
|FF|8.4-SNAPSHOT|(50, 50, 1000)|4421|24|
|IE|8.4-SNAPSHOT|(100, 0, 1000)|8281|36|
|IE|8.4-SNAPSHOT|(50, 50, 1000)|5739|34|

Grid is not only slow with many columns, but with components. I have a grid with about 200 rows that has two columns where one contains a Link:

grid.addComponentColumn(item -> {
  Link link = new Link(item.getNummer(), new ExternalResource("#!detailView/" + item.getId()));
  return link;
}).setCaption("Show Details");

That kills performance already. When I drag the scrollbar, there is a lag of 1 second ca. every 50 rows. I cannot present that to users. It would be more acceptable to load the whole table at once waiting a little longer and then scroll without "stuttering". I'm deeply missing the setPageLength(0) of the old table. I had no success with the CacheStrategyExtension of the GridExtensionPack Add-on. It seems to have no effect.

Edit: Workaround for my problem: Instead of a component add a column with HtmlRenderer that creates a simple link:

grid.addColumn(item ->
"<a class='v-link' href='#!detailView/" + item.getId() + "'>" + item.getNummer() + "</a>",
  new HtmlRenderer())
  .setCaption("Show Details");
Was this page helpful?
0 / 5 - 0 ratings

Related issues

vaadin-bot picture vaadin-bot  路  7Comments

TatuLund picture TatuLund  路  3Comments

vaadin-bot picture vaadin-bot  路  6Comments

FSchliephacke picture FSchliephacke  路  4Comments

RobertZenz picture RobertZenz  路  6Comments