XTranslateCoordinates() performance problem



Taking a look at where GTK+ was spending its time when opaque
resizing over a 10mb network, I noticed something interesting.

For ConfigureNotify events on toplevels, GTK+ does:

          if (!xevent->xconfigure.send_event && 
              !GDK_WINDOW_DESTROYED (window))
            {
              gint tx = 0;
              gint ty = 0;
              Window child_window = 0;
              gdk_error_trap_push ();
              if (XTranslateCoordinates (GDK_DRAWABLE_XDISPLAY (window),
                                         GDK_DRAWABLE_XID (window),
                                         _gdk_root_window,
                                         0, 0,
                                         &tx, &ty,
                                         &child_window))
                {
                  if (!gdk_error_trap_pop ())
                    {
                      event->configure.x = tx;
                      event->configure.y = ty;
                    }
                }
              else
                gdk_error_trap_pop ();
            }
          else
            {
              event->configure.x = xevent->xconfigure.x;
              event->configure.y = xevent->xconfigure.y;
            }

The reason for this is so that event->configure.{x,y} can be
used to track the location of windows ... when you get a
configure event, it is either:

 - A synthetic configure event because the window manager
   moved the window manager frame and then (to conform
   to the ICCCM) sends a synthetic configure.

 - A real configure event because the window manager 
   resized or move/resized the client window.

In the former case, the coordinates are correct, in the
latter, they will be the coordinates within the frame
window. 

Now, in response to a configure-notify where the size
changes (so, a real configure notify, and XTranslateCoordinates()
is called), GtkWindow queues an idle function to do the
resizing if there isn't already one done. Queueing an idle
like this only works if the work done for each event is
small enough so that you eventually go idle. Turns out,
that over 10mb XTranslateCoordinates() takes long enough
so that you can spend all your time translating coordinates,
and none drawing.

Ways of dealing with this:

 1) Not correct event->x, event->y for the app, make
    the app  ask for the new coordinates. There are tricks
    you can play here to make this quite efficient....
    when you get a synthetic configure notify, mark
    the position as unknown, but if you get a
    real configure notify, or any mouse event on
    the window mark it known. (Mouse events on the 
    window allow computation of the position by
    the difference betweeen x,y and x_root,y_root)

    The ICCCM recommends doing something like this.

    Unfortunately, this breaks compatibility and is just
    a sucky interface for the app.

 2) Use the last x, y received for the event, then queue
    an idle with a priority lower than events in which
    you actually call XTranslateCoordinates() and 
    synthesize a pure-move ConfigureNotify if the 
    x, y you retrieve are different than the last x,y.

    This should work quite well since synthetic
    configure-notifies received are almost always pure
    resizes, though there is still a round-trip request
    involved.

    [ A variant you could do on this with a sufficient
    sophisticated X protocol lib (XCB?) would be to
    send a TranslateCoordinates request immediately,
    but don't block for the response; when the response
    receives synthesize a pure-move ConfigureNotify 
    if necessary ]
    
I think 2) may be worth implementing, though opaque resize
over a slow link may be considered a bit of an edge
case so there is no rush.

Anyways, that's my X performance note for the evening,

                                        Owen




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