gEvas: the GTK+2 to Evas Bridge

Learn about some of the Enlightenment Foundation Libraries and how to use them with gEvas for high performance in your next GTK+2 application.
Let's Race Them

The results should be similar on a relative basis no matter what hardware is used. For the sake of completeness, my testing CPU was an AMD XP-Mobile running at 2.4GHz with 200MHz FSB, with 1GB of RAM at 400MHz dual-channel cas222 and and NVIDIA 5900 video card. The software that may affect performance includes xorg-x11-6.8.2-1.FC3.13, either GCC 4.0.0 20050308 (Red Hat 4.0.0-0.32) or GCC 3.4.3. X11 was configured with TwinView with one 1024x768 and one 1600x1200 screen, both running 85Hz in 32-bit color. TwinView should not affect runtimes because all canvases are using software render paths that should be more sensitive to CPU/RAM speed.

Using client libraries qt-3.3.4, libgnomecanvas-2.10.0 recompiled with below CFLAGS, Evas CVS checked out on May 28, 2005. Evas was compiled with GCC 3.4.3 with the below CFLAGS. Benchmark compiled code CFLAGS and CXXFLAGS are generally:

-O3 -march=athlon-xp -fomit-frame-pointer

I benchmarked the qt-canvas-resize client separately because of the image caching distinction and chunk-size optimizations mentioned above. Shown in Table 1 are the benchmarks for qt-canvas-resize, where the Qt part of the main loop consists of:

QCanvasSprite* leaf_sprite = ...;
QCanvasPixmapArray* leaf_tiles = ...;
while( running )
  while( app->hasPendingEvents() )
  QImage im = ... from cache ...;
  QCanvasPixmap* qpix = new QCanvasPixmap( im );
  leaf_tiles->setImage( 0, qpix );

The client has several command-line options: --alpha-blend-image is used to alpha-blend the red rectangle instead of the leaf, and --chunk-size is used to specify a non-default chunk size. The --alpha-blend-image option is common to qt-canvas-resize, gnome-canvas-resize and (g)evas-resize.

Table 1. qt-canvas-resize Benchmarks with Different Tile Sizes

ApplicationChunk sizeLeaf image FPSAlpha rectangle FPS

Running the default chunk-size leaf image qt-canvas-resize through valgrind's callgrind for a few minutes reveals that QCanvas::update() gets 30% overall runtime, with 59% of runtime used by QCanvasPixmap::init(). So the benchmark could be considerably better if the pre-cached images are stored in a QCanvasPixmapArray for the sprite.

To test this level of pre-caching, I added the -Z option to put all of the cache images into a single QCanvasPixmapArray, which is the backing for the QCanvasSprite. With this optimization, 559 FPS can be achieved with 78% of runtime in QCanvas::update() and 7% in QCanvasSprite::setFrame(). It has to be noted that this level of pre-caching presents a unfair advantage for QCanvas for rendering speed.

The GNOME Canvas client for image scale and blend is gnome-canvas-resize, which has an --aa option to choose the GNOME Canvas alpha-blending back end. evas-resize has no custom options.

Table 2. GNOME Canvas vs. (g)Evas in the Resize Benchmark

ApplicationLeaf image FPSAlpha rectangle FPS
gnome-canvas-resize --aa149127

Without the --aa option, gnome-canvas-resize spends 99% of its time inside gtk_widget_send_expose(), which is called one way or another from g_main_context_iteration(). I don't think that the non-aa GTK+2 engine likes being used in a flat-out benchmark manner. Using callgrind on the --aa GNOME Canvas back end finds 96% of its time spent in gtk_widget_send_expose(), although now we can see 66% of the time in gdk_pixbuf_composite() is called indirectly from gtk_widget_send_expose().

evas-resize is spending 99% of its time in evas_render_updates(). Of the functions called from evas_render_updates(), 91% is spent scaling functions.

I also ported the evas-resize to using gEvas and its API calls. Although there is some speed loss due to the GTK+ signal glue and other gEvas trimmings, the loss is not too significant.

This comparison shows that for outright image scaling, GNOME Canvas and QCanvas are similar and both are slower than Evas. Evas gains further ground when the scaled image also needs to be alpha-blended to the background.

I modified the original evas_bench application to remove the use of features not easy to replicate in GNOME Canvas. Other features became optional to measure their impact on overall performance. The setting of clip zones in Evas is not an easy thing to port to GNOME Canvas, so these were disabled in the evas_bench. Smooth scaling also can have a strong impact on performance, so an option to turn that off for the Evas version was added.

Table 3. evas_bench and Its GNOME Canvas Port Head to Head

gnome-canvas-port-evas-bench --aa901.49
evas_software_x11_main --smooth-off-for-some2003.32

It should be noted that Evas doesn't currently implement a cache for scaled images. So every frame in the Evas benchmarks is performing an image scale and blend.

The evas_buffer_test client performs the same work but only renders the output to a 32-bit RGBA image buffer in memory.