stress-testing glitz, cairo and librsvg

I wanted to see how brutal I can be to glitz, cairo and librsvg by not using any buffering via image-surfaces rendering everything straight as svg. This is the example and its sysprof-log. I make this available for the sake of putting out a small but heavy test-case for the cairo-hackers (or the developers behind librsvg). It opens a transparent and decoration-less window and renders 11 svg-icons. Moving the mouse-pointer over them causes a OSX-dock-like effect, where the icon under the pointer gets scaled up and a title blends in above it. All other icons are rearranged accordingly. Each svg-icon is transformed using a cairo-matrix and finally rendered via librsvg. The scaling is triggered by the mouse-motion-event. While I expected this to be a bit of work for the CPU/GPU (using glitz-enabled cairo 1.1.6 here), I never thought it would max out that much. I’m running on an Athlon64 3700+ alongside a GeForce 6600 under Xgl/compiz. Why does this turn out to be such a burden for the CPU? Where’s the bottleneck? I hope someone can point out to me what’s wrong.



just the rects, fast (click to play back, ogg/theora, ~270 KBytes)


full svg-glory, dog-slow (click to play back, ogg/theora, ~600 KBytes)


ATTENTION… it is highly unlikely that I will make a full dock-like application for gnome (or plain gtk+) out of this. This time I will stay strong and resist any forces that attempt to lure me into doing this. It happend with cairo-clock. But not this time *g*. Of course it does by no means prohibit anybody else to pick it up and do so.

16 Responses to “stress-testing glitz, cairo and librsvg”

  1. Joel Calado Says:

    MacSlow dit it again :D

    OH please please please please please please please please please please please do build a gtk+ dock out of this :P

    I beg you!!!!

    ;) Nice to see you’re still fit to keep’em coming after all that ranting from other persons in your blog!

    keep going MacSlow, im a huge fan of what your doing here :D

  2. Daniel Says:

    Hi Marco, tudo bom?

    I remembered having read something similar to that problem in planetgnome. After a bit of investigation I found this:

    http://primates.ximian.com/~federico/news-2006-04.html#limiting-your-repaint-rate

    Maybe it’s an explanation or a solution.

    Good luck. Até mais.

  3. Jones Lee Says:

    I reckon it’s the integrity issues of X and nvidia driver, not to imply that cairo is pretty "raw" and not yet mature or optimized. I found this perfomance comparison http://www.xaraxtreme.org/about/performance.html
    By the way, it would be so sick to see a fully 3D desktop with docking, clock widget, imagine a real or better Mac experience on Linux. I think I shouldn’t lure you to this temptation, rite ;)?

  4. Frank Groeneveld Says:

    Hi Marco,

    This app looks really great! Maybe I will make a OS X like dock bar of it.
    This maxes out your cpu because on _every_ mouse move event you recalculate the size of the icons and their position. And I can tell you, there are a lot of mouse move events. To solve this problem, I think you need to add something like a counter in the mouse move event handler. Let it add every event, and only recalculate when the counter = 100 for example. Or you could use cpu ticks for it.

    Good luck,
    Frank

  5. Frank Groeneveld Says:

    Something like this should work:
    gboolean on_motion_notify (GtkWidget* pWidget,
    GdkEventMotion* pMotion,
    gpointer data)
    {
    int newtime = 0;
    static int oldtime = 0;

    g_fMouseX = pMotion->x;
    g_fMouseY = pMotion->y;

    newtime = pMotion->time;

    if(oldtime == 0)
    oldtime = pMotion->time;

    if(newtime > oldtime + 500) {

    recalc_scales (g_aIcons, SVGS, g_fMouseX);
    recalc_positions (g_aIcons, SVGS, 2.0f);

    gtk_widget_queue_draw (pWidget);

    oldtime = newtime;
    }
    return FALSE;
    }

    Although it doesn’t completely solve it, it’s a bit better already.

  6. MacSlow Says:

    @all: Thanks for the comments and tips sofar (here and via eMail)! I’ll add repaint-throttleing and surface-buffering with the next revision.

  7. Karl Lattimer Says:

    You complete GIT! You beat me to it, although I was going for a pygtk version, and waiting for composite support to come back into pygtk before I even made an attempt. You may want to take a look at http://jrgraphix.net/research/flash-dock-mx-2004.php which was the code I was going to base mine on.

    As far as the speed is concerned, I think there are a couple of contributing factors, firstly nvidia _STILL_ doesn’t have TFP support and my 6800GT runs slow on some compiz effects, because its using software rendering, and also the gconf key /apps/compiz/general/screen0/options/detect_refresh_rate and refresh_rate keys can sometimes be in error, setting the detect to false and the refresh_rate to the same as preferences -> screen resolution says generally increases speed quite a bit.

    Apart from that it be wicked, and I may hack some code back into this one for fun at some point.

    Would you mind if I set up a public SVN for people to use to hack on this?
    Please reply to me via email cheers.

  8. Alan Says:

    Or you could use something like the timer Bahdad used for frame rate limiting in VTE (as used by the Gnome Terminal) which limits output to 40FPS.

    g_timeout_add (25, function, data);

  9. Luca Says:

    Alan, also Federico Mena-Quintero wrote something about that:
    http://primates.ximian.com/~federico/news-2006-04.html#28

  10. Sven Neumann Says:

    The most simple optimization is to request motion-hints instead of dealing with motion events. All you need to do is to add GDK_POINTER_MOTION_HINT_MASK to your window. Then, in the motion event handler, do not use the mouse position from the event struct but query for the current pointer position by calling gdk_window_get_pointer(). See the docs for GdkEventMask for more information.

  11. Hylke Says:

    I wanted to make this thing but I got this error:

    gcc -Wall -O3 -march=k8 -DXK_MISCELLANY -DXK_LATIN1 `pkg-config –cflags glitz-glx cairo gtk+-2.0 librsvg-2.0` -c -o main.o main.c
    main.c:41:32: error: librsvg/rsvg-cairo.h: No such file or directory
    main.c:88: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘g_DimensionData’
    main.c: In function ‘render’:
    main.c:164: warning: implicit declaration of function ‘rsvg_handle_render_cairo’
    main.c: In function ‘main’:
    main.c:332: warning: implicit declaration of function ‘rsvg_handle_new_from_file’
    main.c:332: warning: assignment makes pointer from integer without a cast
    main.c:333: warning: implicit declaration of function ‘rsvg_handle_get_dimensions’
    main.c:333: error: ‘g_DimensionData’ undeclared (first use in this function)
    main.c:333: error: (Each undeclared identifier is reported only once
    main.c:333: error: for each function it appears in.)
    make: *** [main.o] Error 1

    How to fix? :S

    Thanks

  12. MacSlow Says:

    @Hylke: *cough.cough* Install librsvg 2.14.x and related development-files.

  13. Hylke Says:

    Got it working, thanks.

  14. setenza Says:

    /usr/bin/ld: ne peut trouver -lGLU

  15. MacSlow Says:

    @setenza: Il n’y a aucun besoin de -lGLU. Tu peut le laisser tomber. (I hope I did not totally screw that up… for me french is magnitudes more difficult than english).

  16. setenza Says:

    Working thanks

Leave a Reply