Rendimiento y optimización de GWT FlexTable

I'm working on GWT project where we are using FlexTable to display some data. I know that we should probably be using CellTable as it has better performance, but FlexTable is easier to style (style specific cells) and makes it easier to update specific cell.

To receive updates for the table we're using WebSockets. The problem we're facing right now is high CPU load when there're more than 100 updates per second coming through WebSockets. Each message from WebSocket connection contains updates for several cells in the table. So in practice there're more than 100 updates per second that should be rendered in the FlexTable. CPU load on my 3GHz i5 with 4GB RAM is around 50%. If I disable actual rendering of the data (comment out setText() method calls) then CPU load goes down to 5-10%. So I know that DOM updates are the bottleneck, not the other parts of the code.

Seria mejor

  1. use Grid instead
  2. switch to CellTable (but how to make singe cell updates then)?
  3. use JS/JSNI to work with DOM instead of FlexTable setText()

Are there better ways to implement table and improve performance?

I've tried to google if someone had similar problems with FlexTable, but found only the general opinion that it is just slow, nothing specific. We have application prototype done purely in JavaScript and with same 100 updates per second CPU load is around 15%

Dropping css fade effect which we used to indicate change in the cell value reduced CPU load by ~10%. So it seems that the DOM is not the only problem.

preguntado el 09 de noviembre de 11 a las 12:11

3 Respuestas

With a CellTable you have to re-render the entire table to update a single cell. However, such an update would be a single update to the DOM. With a FlexTable, even if you batch all of your updates together, you'll be doing a bunch of separate DOM manipulations. So, even though it might seem inefficient to use a CellTable because you update some cells redundantly, it may still be worth it to switch. Especialmente in the case where you're updating a number of cells close to the total number of cells: batch 100 updates together and do them all at once for a single DOM write.

I have an app with a CellTable that can be as large as 30x100. It has arbitrary styles on arbitrary cells, each cell has complex contents (an <img>, algunos <div>s, and some text) and sometimes I need to update a single cell. Redrawing the whole thing is unnoticeable (to my human perceptions) on my macbook pro in development mode.

If you want live updates (e.g. 100 updates per second, as they happen) then I think you might want a different platform. Not even your monitor is refreshing 100 times per second.

respondido 09 nov., 11:19

In some cases we might have 100 rows in the table with 8 columns. 6 of the columns are updated with data from WebSocket feed. In our simulation we generate 1 message every 10 ms and in total that gives us 100 messages per second, 600 DOM updates. That is too much for FlexTable to handle. But it is quite easy to notice that data is updated rapidly because it is updated in different places (cells). One way to minimize it would be to use JSNI and replace whole row with one DOM update. But I'm not sure that GWT won't do something else after that when code is compiled from Java to JavaScript. - dimchez

Are you saying that you want a sort of sparkling effect at 100hz, with the updates happening in different places at different times? In that case, I think any <table> structure is inappropriate - it's too much updating. What about a canvas element, or Flash? - Alondra riley

If you don't need the sparkling, and just want to update all 100 rows at once, once per second, you should totally use a CellTable. - Alondra riley

No, we need to be able to update each cell independently (best case scenario). JavaScript prototype is able to handle same 100 messages per second with only 10-15% CPU load (same machine). So I know that it should be possible. I just need to find the best possible way to do it in GWT. CellTable does not seem to be the best choice. - dimchez

As an alternative (or in addition to, depending on what results you get) to all of the above I would look into using some of the Scheduler methods. Especially Scheduler.get().scheduleIncremental() and do updates in batches of say 10 at a time. This will allow the browser to process other events in between updates and should have a positive effect on the CPU usage.

CellTable is not going to help you at all here because you cannot update individual cells. So as an alternative it leaves you only the Grid and manually managing a TableElement.

respondido 09 nov., 11:18

Actual update of the cell is done inside SchedulerImpl.get().scheduleDeferred() but that does not help much. Although it keeps browser more responsive. Using SchedulerImpl.get().scheduleIncremental() would not work because amount of data we get may vary. So far it looks that we should try out Grid or implement Table ourselves. - dimchez

Incremental is, by far, much better than deferred in this case. Deferred will use a new js timer per operation, whereas incremental will batch multiple updates into a single js execution stack, resulting in a single page redraw, allowing the rendering thread to also do operations in batch. - Ajax

Puede usar el cellTable.redrawRow(index); which is faster on big tables.
The good thing is that the row index is given by the FieldUpdater.

Respondido 30 Oct 12, 18:10

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.