Editable List unusable in IE, slow in all other browsers.

We are now looking into the sluggish UI in our application.
Up until now we have just assumed it was the database access, network latency, Garbage collection etc, but it now seems the major culprit is the Vaadin List.

To exlude most other factors I made myself a tiny test app:

[code]
package com.example.test_list;

import javax.servlet.annotation.WebServlet;

import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;

@SuppressWarnings(“serial”)
@Theme(“valo”)
public class Test_listUI extends UI {

@WebServlet(value = "/*", asyncSupported = true)
@VaadinServletConfiguration(productionMode = false, ui = Test_listUI.class)
public static class Servlet extends VaadinServlet {
}

public static class Row {
    String data = new String[20]

;

    public Row(int rowNo) {
        for(int col=0; col<data.length; col++) {
            data[col]

= "Row " + rowNo + ", col " + col;
}
}

    public String get0() { return data[0]

; }
public String get1() { return data[1]
; }
public String get2() { return data[2]
; }
public String get3() { return data[3]
; }
public String get4() { return data[4]
; }
public String get5() { return data[5]
; }
public String get6() { return data[6]
; }
public String get7() { return data[7]
; }
public String get8() { return data[8]
; }
public String get9() { return data[9]
; }
public String get10() { return data[10]
; }
public String get11() { return data[11]
; }
public String get12() { return data[12]
; }
public String get13() { return data[13]
; }
public String get14() { return data[14]
; }
public String get15() { return data[15]
; }
public String get16() { return data[16]
; }
public String get17() { return data[17]
; }
public String get18() { return data[18]
; }
public String get19() { return data[19]
; }
}

BeanItemContainer<Row> container;
Component component;

@Override
protected void init(VaadinRequest request) {
    final VerticalLayout layout = new VerticalLayout();
    layout.setMargin(true);
    setContent(layout);

    final Label message = new Label("<timing>");
    layout.addComponent(message);
    
    container = new BeanItemContainer<>(Row.class);

    for(int i=1; i<100; i++) {
        container.addBean( new Row(i));
    }
    
    Button button = new Button("Add plain list");
    button.addClickListener(new Button.ClickListener() {
        public void buttonClick(ClickEvent event) {

            if(component!=null) {
                layout.removeComponent(component);
            }

            long start = System.currentTimeMillis();
            Table table = new Table("Plain text", container);
            component = table;
            layout.addComponent(component);
            message.setValue("Plain list added in " + (System.currentTimeMillis()-start) + "ms");

        }
    });
    layout.addComponent(button);

    button = new Button("Add editable list");
    button.addClickListener(new Button.ClickListener() {
        public void buttonClick(ClickEvent event) {
            
            if(component!=null) {
                layout.removeComponent(component);
            }
            
            long start = System.currentTimeMillis();
            Table table = new Table("Editable", container);
            table.setEditable(true);
            component = table;
            layout.addComponent(component);
            message.setValue("Editable list added in " + (System.currentTimeMillis()-start) + "ms");
            
        }
    });
    layout.addComponent(button);

    button = new Button("Add html table");
    button.addClickListener(new Button.ClickListener() {
        public void buttonClick(ClickEvent event) {
            
            if(component!=null) {
                layout.removeComponent(component);
            }
            
            long start = System.currentTimeMillis();
            StringBuilder sb = new StringBuilder();
            sb.append("<table>\n");
            
            for(Object itemId : container.getItemIds()) {
                sb.append("<tr>");
                
                BeanItem<Row> beanItem = container.getItem(itemId);
                
                for(Object propertyId : beanItem.getItemPropertyIds()) {
                    sb.append("<td>").append(beanItem.getItemProperty(propertyId).getValue()).append("</td>");
                }
                
                sb.append("</tr>\n");
            }
            
            sb.append("</table>\n");
            
            Label label = new Label(sb.toString());
            label.setContentMode(ContentMode.HTML);
            component = label;
            layout.addComponent(component);
            message.setValue("HTML table added in " + (System.currentTimeMillis()-start) + "ms");
            
        }
    });
    layout.addComponent(button);

}

}
[/code]I have then run this in different browsers and timed it with ?debug, from first output to last.
There are 3 buttons, each replacing the existing table with a new one.

Each button renders the same Container with 20 columns by 100 rows.


html table

The simplest one is the button that just renders it as an html table. I added this to get a sense of what the lowest possible time would be. In all browsers I got a response time of 100-200ms. This includes the network traffic and is quite acceptable.


Non-editable Vaadin list

The next one renders a non-editable Vaadin list. Chrome is almost as fast as the plain html, returning this in 250ms or so, but Firefox now takes 700ms and the different IE versions take from 900 to 1400ms.


Editable Vaadin list

The final one is the button that returns an editable Vaadin list. Chrome is still fastest, but at 2600ms it is far from fast. Firefox takes 5500ms, and IE takes from 2800ms to a whopping 22 seconds! (Only verified these extreme timings in IE10)


Conclusions?

So, at 2.6 seconds rendering time an editable table like this is just barely usable in Chrome, especially when we add in database access and all the other parts of our application.

IE10 initially rendered the table in a comparable 4 seconds. It was when I clicked again and replaced the table with a new instance that it took from 10 to 20 seconds! Already at 4 seconds, this is pretty useless, but our application will also be replacing the data (when another parent is selected) so we are seeing these 10 to 20 rendering times as well…

Note: I use default List settings, which means Vaadin fetches 10 rows or so at a time. This means that my test list is fetched in 2 separate requests. It is possible I would have gotten a bit better timings if I had tuned the page size so that it had been fetched in one go, but I don’t think it would matter much. Each actual request only takes 10-40ms.

It seems my options are to let the table remain as non-editable, and create some sort of row editor, or to just wait 1-2 months for the new Grid component…

Anyone else had a similar problem? How did you work around it?

Hi,

unfortunately you’re correct - the editable mode is horribly slow especially on IE. Usually I’ve worked around this using a custom TableFieldFactory which only returns field for the row that the user has e.g. clicked on - other rows will be shown as read-only. This will minimize the amount of components in the Table and speed up things considerably.

Please see
https://vaadin.com/forum/#!/thread/189088
for some ideas.

-tepi

Yes, this is what we ended up doing as well.

Next problem then was to make another row editable when clicking on it.
This didn’t work when we did it from the valueChange event, but we got a workaround when we submitted a bug report:
http://dev.vaadin.com/ticket/14684
.

In addition we have had to add code to make this work nice; For instance we have to style the non-editable fields to show where the user can click to edit, we have to make sure the focus is set in the field you click, and to make sure checkboxes are displayed sensibly both when editable and non-editable. Etc.

All in all a lot of work to make an essential component (the most essential?) of the framework work.

Well great to hear you got it working at least :slight_smile: I do agree that Table has too many issues. It’s too monolithic for anyone to test all the use cases and once you fix something it breaks something else :(.

I really hope the upcoming Grid will address at least most of these issues.

-tepi