Posts Tagged ‘X11’

Adventures in X Programming

Saturday, July 5th, 2008

I have reached the end of an over 3-week exploration into the possibility of gaining a nominal speed improvement in Firefox page load times on Linux. Vlad asked me to look into using the Xlib Shared Memory Extension (XShm) for image rendering. I have created an extension to Cairo that can use XShm and plugged that into Firefox’s image library, but now that it is working, the performance results are mixed and I am unsure what to do with it.

Let me explain exactly for what XShm would be useful in Firefox: Faster rendering of images while they are decoding. Some readers of my last post seemed to be under the impression that static images were being drawn using XPutImage and the plan was to use XShmPutImage instead, which given the way I wrote the article (namely, badly), I can’t really blame them. Let me rectify.

X

In Firefox, while images are being decoded, the partial image is constantly being drawn to the screen. Once the image is complete, it is of course optimized into a pixmap on the server, but until that time, it’s constantly being sent to the server via XPutImage. This is where XShm could conceivably help.

However, there is one hitch in this process. Due to the asynchronous nature of X, setting up the XShm image can fail under a certain chain of events, so the application has to synchronize with X (by calling XSync) before destroying the image. This throws a major wrench in application speed if these images are created all the time.

When I ran Talos on a Firefox that used XShm for images, timings were all over the place. Some web pages showed a noticeable improvement in performance, while others showed a noticeable regression in performance. Fiddling with the code, I was able to get it to the point where there was a sizable overall performance improvement on my machine, but I really can’t be sure that will translate into the same thing on most Linux machines.

So I am now at the quandary of deciding what the heck to do with all this work. It seems so close to being something very useful, yet I can’t seem to draw consistent results out of it. There would most likely be regressions across the board for certain machines or web sites. I suppose I’ll let it sit around for a while until I decide how I can improve it.

Cairo, Xlib, and the Shared Memory Extension

Friday, June 27th, 2008

Update: As mentioned in a comment, XShm isn’t always available, for any number of reasons (most usually a remote X server). In this case the program would fall back to the normal method of images. This is why I choose to implement the XShm as a separate surface. The surface creation will fail if XShm isn’t available,  so the application can fallback to a more suitable surface. (And yes, the fact that it’s faster is bloody obvious; I’m as surprised as anyone that Cairo didn’t use it already. ;) )

Maybe I’m just naive, but designing a graphics API such that all image data had to be sent over a socket to another process every time the image needed to be drawn seems like complete idiocy. Unfortunately, that is precisely what the X Window System forces a program to do, and exactly what Cairo does when drawing images in Linux—a full copy of the image data, sent to another process no less, every time it is drawn. One would think there would be some room for improvement.

The X11 LogoUnsurprisingly, others felt the same way about X, and decided to write an extension, Xlib Shm or XShm for short, that allows images to be placed in a shared memory segment from which the X server reads which allows the program to avoid the memory copy. GTK already makes use of the XShm extension, and it seems like a good idea to see if Gecko couldn’t do the same.

An Xlib Shm Surface

There have been previous talks about putting such an extension into Cairo, but none of them have gone farther than a proposed patch. So over the past couple weeks I’ve looked into exploring XShm and Cairo to see whether a clean API can be made for Cairo and to measure just how real the potential speed improvements are.

I implemented a new back end surface for Cairo, cairo_xlib_shm_surface_t. It is designed with one specific use case in mind: the fast rendering of images loaded from files. Generally, one would create the XShm surface, and decode the image directly into the surface, then paint the surface to the screen. It is minimally invasive on the Xlib surface back end, adding only one if block into a single function, and so should have no impact on performance when compiled into Cairo but not used.

The patch was created relative to the git repository for Cairo, taken out on June 10, 2008. You can find the patch at http://www.ericbutler.net/demos/mozilla/2008/cairo-xshm-test/xshm.diff. Configure with the flag --enable-xlib-shm to build it, and include cairo-xlib-shm.h for the functions to create an XShm surface.

Testing

A C program was used to test the new backend for speed. The test compared rendering speeds of painting an image surface on an Xlib surface (the current method of rendering images in Firefox) to painting an Xlib Shm surface on an Xlib surface. The test allocates space for some number of images and fills them all with data. It then draws all the images to the screen, syncs with the X server to make sure drawing is complete, and lastly destroys all the images.

The test was run with images of various sizes, with alpha blending and without. The tests were run on an HP nc8430 laptop with an ATI card running Ubuntu 8.04 using the fglrx drivers. Two different items were measured:

  1. The total time to create, draw, and destroy all the images.
  2. Only the time to draw the images.

Results

Each chart indicates the size of the image, video driver used, measurement taken, and bit depth. The x-axis represents the number of images rendered each test, and the y-axis is the total time of the operation in milliseconds, averaged over 100 tests. The “image” category is a Cairo image surface, and “xshm” is my Cairo Xlib Shm surface. Only a small sampling is shown here, a page with more results can be found at http://www.ericbutler.net/demos/mozilla/2008/cairo-xshm-test/results.html.

Analysis

There are a few observations that can be made instantly from the data:

  • Drawing with XShm is a lot faster. The average speed of the drawing with XShm for any image size was somewhere between 40 and 70 percent the speed of a standard image, which is a pretty good improvement. Image-heavy sites could potentially see a noticeable decrease in page draw time.
  • Creating an XShm surface costs more than an image surface. There appears to be a constant (or at least sub-linear) but noticeable cost to creating a shared memory segment. The total time results for the small image are actually quite worse for XShm, which seems to indicate that there is some lower bound where the cost of setting up the shared memory segment outweighs the benefits gained from the draw call. However, even for images as small as 200×200, even if the image is only drawn once, XShm still provides a net gain in performance. And, of course, the more an image is drawn per creation, the less this overhead matters.

So it seems that XShm is worth pursuing. Further research will need to be done to see how XShm performs with other video drivers such as vesa. I will be exploring how to use this surface in Thebes and image library. Hopefully this can result in a speedup for Firefox on Linux and any and some other Cairo applications that use the Xlib backend.

X11 logo image taken from http://commons.wikimedia.org/wiki/Image:X11.svg.