views:

364

answers:

4

Is there a way to speed up the population of a page with GWT's UI elements which are generated from data loaded from the datastore? Can I avoid making the unnecessary RPC call when the page is loaded?

More details about the problem I am experiencing: There is a page on which I generate a table with names and buttons for a list of entities loaded from the datastore. There is an EntryPoint for the page and in its onModuleLoad() I do something like this:

final FlexTable table = new FlexTable();

rpcAsyncService.getAllCandidates(new AsyncCallback<List<Candidate>>() {
    public void onSuccess(List<Candidate> candidates) {
       int row = 0;
       for (Candidate person : candidates) {
          table.setText(row, 0, person.getName());
          table.setWidget(row, 1, new ToggleButton("Yes"));
          table.setWidget(row, 2, new ToggleButton("No"));
          row++;
       }
    }
    ...
});

This works, but takes more than 30 seconds to load the page with buttons for 300 candidates. This is unacceptable.

The app is running on Google App Engine and using the app engine's datastore.

+1  A: 

The significant thing here is how you're retrieving the list of candidates, which you haven't shown. 30 seconds is extremely high, and it's unlikely that it's due to the datastore alone.

Have you tried using appstats to profile your app?

Nick Johnson
+5  A: 

You could do a lot of things, I will just list them in order that will give you the best impact.

  1. FlexTable is not meant for 300 rows. Since your table is so simple, you should consider generating the HTML by hand, and then using simple HTML widget. Also, 300 rows is a lot of information - consider using pagination. The DynaTable sample app shows you how to do this.
  2. It looks like you are using one GWT module per page. That is the wrong approach to GWT. Loading a GWT module has some non-trivial cost. To understand what I mean, compare browser refresh on gmail v/s the refresh link that gmail provides. That is the same cost you pay when every page in your website has a distinct GWT module.
  3. If the list of candidates is needed across views, you can send it along with the HTML as a JSON object, and then use the Dictionary class in GWT to read it. This saves you the RPC call that you are making. This approach is only recommended if the data is going to be useful across multiple views/screens (like logged in users info)
  4. Check how long your RPC method call is taking. You can enable stats in GWT to figure out where your application is taking time.
  5. You can also run Speed Tracer to identify where the bottleneck is. This is last only because it is obvious FlexTable is performing a lot of DOM manipulations. In general, if you don't know where to start, Speed Tracer is a great tool.
sri
+1  A: 

Like sri suggested - pagination is easiest and (I think) best solution (along with switching to Grid or just <table>). But in case you wanted for some reason to show/render many rows at once, the GWT Incubator project has a nice wiki page about it - along with some benchmarks showing how FlexTable sucks at large row count. Check out their other tables too ;)

Igor Klimer
+1  A: 

Your problem is that everytime you add something to the FlexTable it has to re-render the whole page and repaint. Try creating a new FlexTable, populating it, when it is fully populated, get rid of the old one and put the new one there.

Romain Hippeau