Re: Some performance notes

Owen Taylor <otaylor redhat com> writes:

> So, without including hard data (I don't have much), here are
> my observations:

I think it is important to also do some measurements with real
applications to see which parts of Gtk they spend their time in.

>  * With debugging turned off, the bulk of time was spent in
>    the signal emission code and its GValue handling (40-50%)

Speeding up signals may be a matter of caching.  I can easily imagine
time-critical code emitting the same signal over and over.  I don't
know if caching makes any sense in the code, though.

>  * When opaque-resizing, another ~10 percent of non-debug time
>    was spent maintaining invalid regions. This is probably quite 
>    optimizable - some extra region copies are made, and it looks like 
>    that adding a "completely invalid" flag to GdkWindow might allow bypassing
>    a bunch of computations, since it seems like windows were
>    getting invalidated repeatedly.

The tests I have been doing are concerned with snappyness or
interactive performance. 'Snappyness' is really measured in how many
event can we respond to when 'something is going on', like opaquely
resizing something.

To experiment with interactive performance, I made panes resize
opaquely and resizes take effect immediately. Then I put a VPane in
the toplevel window in testgtk and ran the whole thing under a
profiler and tried to extract from the call-graph where the time was
spent /when responding to events/.

The result was that by far the most time was spent redrawing (and a
non-negligible amount on gtk_widget_style_get()).  

This is good, because drawing means something entertaining is going on
on the screen, which is another way of saying that it feels snappy.
It also means that if resizes are handled this way, speedups to the
drawing code immediately translates into snappyness.  In fact, it
doesn't even have to be speed-ups - just moving time-consuming stuff
out of the interaction loop helps a lot.  (At some point I introduced
a low priority idle loop to take care of calls to g_object_unref -
this really made a difference).

One speedup that is applied in the attached patch was not at the
drawing code itself, but rather in avoiding a lot of unnecessary
drawing.  Every resize currently results in a total redraw of
everything in the widget tree.  This happens because queue_resize()
calls queue_clear() and again because size_allocate calls queue_draw()
on all widgets that changed size which invalidates a widget *and all
of its child widgets*.

The attached patch only redraws widgets that actually changed size (or
moved in the case of NO_WINDOW widgets).  The problem with this is
that windows that are exposed are not redrawn until the server send an
expose event, and that can take a while.  The patch attends to this
problem with a cheasy hack that fakes two expose events (yes, it is
bad, and yes, I know it really doesn't work).

In general, the patch is certainly not production code (don't opaque
resize the windows two much - it handles every single ConfigureNotify
event.  And don't look at the changes to gtkwidget.h or at the
gtk_widget_create_window()).  However, it does demonstrate that
improvements to interactive performance are possible.

>    A lot of creation and destruction of graphics contexts and 
>    setting of clip rectangles could be avoided. This probably
>    would cut down the client side overhead to very little. 

That was my observation too.  Caching the GCs instead of creating and
destroying them made a significant difference.  Also caching of the
backing store pixmaps made a difference.

>  * Most of the other time spent looked pretty spread out - though
>    once we tackle the obvious stuff, more bottlenecks may
>    be apparent.
> Generally, on my tests on a 400mhz celeron I felt fairly good about
> the overall performance with debugging off. 

> Opaque resizing was a little more sluggish than I would like, but
> other operations seemed pretty snappy, and it would definitely have
> been useable on a slower machine.

Opaque window resizing sucks currently because resizes are queued up
and not handled until the idle loop - essentially, Gtk is throwing
most of the ConfigureNotify events away instead of handling them.  My
guess would be that configure compression plus immediate resizes would
help, but I haven't tried it yet.


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]