Eclipse on SWT/GTK+ Performance Notes

Billy Biggs <vektor@dumbterm.net>

The following is a summary of some of the investigations into improving the performance and visual appearance of Eclipse on SWT/GTK+. This list is by no means exhaustive or authoritative, and suggestions or updates are greatly appreciated.

GTK+ can send expose events to obscured widgets

When an X Window object is resized, GTK+ will aggressively tell widgets to paint themselves rather than wait for the X server to send an expose event. This can improve the responsiveness during operations such as resizing the pane in a GtkPaned widget.

However, GTK+ has no the concept of widget Z-order, and is not able to track whether a Window is being obscured. Therefore, GTK+ can send expose events to widgets that may not currently be visible.

In Eclipse, our editor widgets are never hidden, they are simply stacked on top of each other and rely on widget Z-order. When our editor area was resized, all active editors were being told to paint rather than just the one on top.

The workaround for 3.0 was to try tracking widget VisibilityNotify events, and only honour expose events that are sent to widgets we believe are visible. There may be other cases where this is hurting us, and similarly any GTK+ widgets we obscure and then resize will not perform this optimization.

One also has to be careful about invalidating GTK+ widgets. GTK+ does not send invalidation events through the X server, and therefore any invalidated area will be painted regardless of its visiblity (though GTK+ does first check to make sure the Window is mapped). I am not sure if this behaviour in particular affects Eclipse.

Widget background colours

If you move an xterm in front of a busy or hung Mozilla Firefox window, you will see a trail behind your xterm like this:

This is because Firefox's widgets tell the X server not to fill them to their background colour. In general, GTK+ widgets never use this technique. One of the reasons may be background pixmaps: the X server will efficiently draw the background image itself. Here is the same test done to a GTK+ application:

This application has a GtkTreeView with a white background window, and the main window behind it has the normal widget background colour:

If we try this with a theme with a background pixmap, we can see that X will tile background pixmaps for free, even when the application is unresponsive:

This behavioural difference between Eclipse and Firefox also explains the visual appearance of menus in GTK+ 2.4.x and earlier. See:

By honouring SWT.NO_BACKGROUND on the editor widget, we were able to avoid flicker on switching editor tabs in Eclipse. However, there is still flicker on editor close, probably because we destroy the widget and X paints the widget behind it to its background colour. This flicker does not exist with GTK+ 2.5 CVS due to the patches from GNOME bug 113310.

setRedraw(), widgets drawing when they should not

SWT has an API (Control.setRedraw) to shut off drawing for a widget and all of its children. This is for when you want to perform operations that may paint directly to their widgets or force repaints, and have these drawing operations be dropped to avoid flicker. This is used in some parts of Eclipse.

There is some limited GTK+ API for freezing drawing on widget windows. However, this only stops the idle loop from dispatching expose events, not prevent drawing by widgets themselves (or by widgets that explicitly paint). As well, if the Z-order of an X Window is changed, then X will paint the background colour if set, and this cannot be prevented.

For Eclipse 3.0, setRedraw() was implemented by obscuring the Control with a new X Window set to have no background colour or pixmap. When drawing is turned back on, the window disappears and the contents behind get an expose event.

Performance differences between GTK+ themes

GTK+ themes can have a large impact on performance. The best example we have of this came from some benchmarks of switching perspectives in Eclipse. The "Bluecurve" GTK+ theme shipped with Red Hat 9 was shown to slow down our benchmark by almost 30% compared to other themes.

Mouse motion hints

Before Eclipse 3.0, the mouse motion hint mask (GDK_POINTER_MOTION_HINT_MASK) was not being used correctly. This caused far too many mouse motion events to be passed to Sashes, which significantly hurt the performance of fast view resizing.

Fixing this may have fixed other widgets that relied on motion events. However, GtkTreeView widgets in particular do not set this hint, and sometimes it seems that SWT gets more mouse events than expected.

The bug that shows this problem is the editor drop down that appears when you hit Ctrl-E, and the lists that appear by Ctrl-O and Ctrl-T. Sometimes when they first appear, too many mouse events are received and the selection lags far behing the mouse pointer. This can be worked around by enabling the mouse motion hint on the GtkTreeView widget in GTK+ itself.

However, Owen Taylor noted in the October 25th GTK+ team meeting that this would be a breaking change, and that he thinks the problem may be elsewhere.

GtkTreeView performance

Eclipse uses a lot of GtkTreeView widgets (SWT's Table and Tree). As well, GtkTreeView is used in the implementation of GTK+'s combo boxes.

Rutger Ovidius found a performance difference between GTK+ and other toolkits in the speed of very large tables and combo boxes. Some research into this showed that unlike tree widgets on other platforms, GTK+ allows for rows to not all have the same height, which means that they must calculate the height of every row before they can decide how to draw the scrollbars.

GTK+ version 2.4 introduced a new "fixed-height-mode" property for tree views, but it has some limitations and is not used in their combo box implementation. This property is used if available by the SWT implementation of SWT.VIRTUAL for Trees, and maybe we can use it in more situations.

Antialiased text rendering

Antialiased text rendering on Linux systems can be slow. Antialiased fonts must be composited by the X server, and on most drivers this has been implemented by reading back the contents of the framebuffer, compositing in system memory, and then writing the result back. Søren Sandmann has done some work on improving the performance of the X server, and his modifications went into X.org's server version 6.8.0.

Furthermore, pango itself does work to perform correct i18n layout, and this in itself incurs a speed difference as well. It is unclear how much this affects the performance of Eclipse in general.

In Eclipse 3.0.0 and earlier, listing fonts can be slow

The algorithm used in Eclipse 3.0.0 and earlier for listing fonts ends up being O(n3) when Pango used its fontconfig back end. This was fixed for Eclipse 3.0.1. For users with a lot of fonts, Eclipse startup time could take minutes.

X protocol bandwidth

At one point, SWT was sending large images to X and letting it perform clipping, which hurt performance for remote X users:

It may be interesting to try again to profile the image data sent to the X server and ensure that the bandwidth used is reasonable.

Other resources