Monday, July 16, 2012

SWT Table Simple Performance Improvement

If you have ever used the SWT Table widget for any serious amount of data, you may have noticed that the performance is, let's say not great. One way to improve the performance of the SWT Table is to use the SWT.VIRTUAL style and fill the data "on demand". While this does work, there is another very easy way to improve it noticeably.

The trick is using the redraw flag correctly. Normally, the redraw flag is set true by default, which means that the widget redraws with any change whatsoever. So, for example, adding a TableColumn or a TableItem (new row) means a redraw. Of course, if you are filling thousands of rows into a table, the performance is usually quite poor.

You can just set the redraw flag to false before filling the table and set it to true after filling it. As an example, take a look at an example, adapted from the snippet here.



import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;


public class TableShellExample {


  Display display;


  Shell shell;


  TableShellExample() {
    display = new Display();
    shell = new Shell(display);


    shell.setSize(300, 500);
    
    shell.setText("A Table Shell Example");
    shell.setLayout(new FillLayout());


    Table table = new Table(shell, SWT.BORDER);


    TableColumn tc1 = new TableColumn(table, SWT.CENTER);
    TableColumn tc2 = new TableColumn(table, SWT.CENTER);
    TableColumn tc3 = new TableColumn(table, SWT.CENTER);
    tc1.setText("Column 1");
    tc2.setText("Column 2");
    tc3.setText("Column 3");
    tc1.setWidth(80);
    tc2.setWidth(80);
    tc3.setWidth(80);
    table.setHeaderVisible(true);


    shell.open();
    
    // turn redraw off before filling table
    table.setRedraw(false);
    
    long start = System.currentTimeMillis();
    
    for (int i = 0; i < 5000; i++) {

    TableItem item = new TableItem(table, SWT.NONE);
    item.setText(0, "A "+i);
    item.setText(1, "B "+i);
    item.setText(2, "C "+i);
}


    // turn redraw on again after filling table
    table.setRedraw(true);
    
    long end = System.currentTimeMillis();
    System.out.println("Filling table took "+(end-start)+" milliseconds.");
    
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch())
        display.sleep();
    }
    display.dispose();
  }


  public static void main(String[] args) {
    new TableShellExample();
  }


}


Performance?

Well, on my humble system, the code without switching the redraw off and on took, on average 797 milliseconds.

By turning off redraw before filling and turning it on after filling, this drops to 70 milliseconds on average.

So, just by setting a flag off and then on again, you can make the standard SWT Table more than 10 times faster.

No comments:

Post a Comment