Community
Participate
Working Groups
If a table has many elements (e.g., a virtual table with 100k entries), the selection takes quite a lot of time to respond to a mouse click (~1 second). I have investigated the bottleneck, and found it to be in function gtk_tree_selection_selected_foreach of class OS (line 6245). In my particular scenario (Linux FC2, 1.6GHz Centrino, 100k entires, table styles SWT.MULTI and SWT.VIRTUAL), this function gets called three times per selection, each time requiring some 0.3 seconds (with some 70ms between two consecutive calls). The calls are due to a call to Table.getSelection(). The Table.getSelection() also creates an integer array with the same number of elements as there are items in the table. In itself, this doesn't take much time, but may consume a lot of memory (e.g., 20 mio entries). Is there a way to optimize this interaction with GTK? I have a feeling that performance with Eclipse 3.0 was better in this regard (but I haven't quantitatively measured this -- it's just a vague recollection). Perhaps only an array of selected indices could be retrieved from the GTK?
Thanks for the detailed analysis of what's going on, I'll see what's up.
Here is the test app I'm using. Seems much slower than I would expect. public static void main(String[] args){ Display display = new Display (); Shell shell = new Shell(display); shell.setLayout(new FillLayout()); final Table table = new Table(shell, SWT.MULTI | SWT.VIRTUAL); table.addListener(SWT.SetData, new Listener() { public void handleEvent(Event event) { TableItem item = (TableItem) event.item; item.setText("Item"); } }); table.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { long before, after; before = System.currentTimeMillis(); table.getSelection(); after = System.currentTimeMillis(); System.out.println("Time: " + (after-before) + " ms."); } }); table.setItemCount(100000); shell.open(); while (!shell.isDisposed ()) if (!display.readAndDispatch ()) display.sleep (); display.dispose(); }
Created attachment 24588 [details] Patch to Table.java Here is a patch that makes the time much more reasonable on my machine. The fix was to use gtk_tree_selection_get_selected_rows() instead of gtk_tree_selection_selected_foreach(). It is not yet clear to me why there is such a large difference. I will clean the patch up a bit before I commit it, but I think we should also determine what was wrong with using the foreach function.
Using gtk_tree_selection_get_selected_rows() is also better since we don't need to allocate the big array. The function is new for GTK+ 2.2, but we already depend on GTK+ > 2.2 in other places so it's no longer an issue. This is probably why the foreach was being used in the first place.
Created attachment 24591 [details] GTK+ test case For reference, here's a small GTK+ test app. Using foreach is at least 10x slower than get_selected_rows. AFAICT, the difference is in maintaining the iters for the callback, as this needs to query the model. I'm not convinced there's a GTK+ bug here, but the large difference in performance is unexpected.
Fixed > 20050712 in SWT for Table, Tree, and List. Kristian Rietveld has fixed the upstream problem in GTK+ CVS, so as of GTK+ 2.8.0 the performance of both functions will be the same. The extra cost was from maintaining the iters, and it was fixed by only obtaining an iter for the selected items.
For reference, here was the change in GTK+: 2005-07-13 Kristian Rietveld <kris@gtk.org> * gtk/gtktreeselection.c (gtk_tree_selection_selected_foreach): quit maintaining the iter on every iteration, only get the iter when we are about to call the foreach_func. Gives us a 10x speedup, since maintaining iters is a lot more expensive than maintaining paths. We lose a bit of sanity checking though. Thanks go to Billy Biggs for pointing this out.