XForms: Re: Big time lag using XCopyArea, and get_next_event() event backlog problem.

From: jac@casurgica.com
Date: Wed Apr 23 2003 - 02:18:21 EDT

  • Next message: Angus Leeming: "Re: XForms: Re: Big time lag using XCopyArea, and get_next_event() event backlog problem."

    # To subscribers of the xforms list from jac@casurgica.com :

    Ok so I know exactly what the problem is:

    I made it so that select_form_event writes the Window of the canvas on my
    test form, along with the Window that the XEvent is for and the event type
    itself to the log file in addition to all the other stuff. Here is a small
    excerpt:

    [win=0x200003c canvas=0x200003c 0 NoExpose] 122 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 121
    [win=0x200003c canvas=0x200003c 0 NoExpose] 121 121 TO WATCH
    IO!
    [win=0x200003c canvas=0x200003c 0 NoExpose] 121 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 120
    [win=0x200003c canvas=0x200003c 0 NoExpose] 120 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 119
    [win=0x200003c canvas=0x200003c 0 NoExpose] 119 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 118
    [win=0x200003c canvas=0x200003c 0 NoExpose] 118 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 117
    [win=0x200003c canvas=0x200003c 0 NoExpose] 117 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 116
    [win=0x200003c canvas=0x200003c 0 NoExpose] 217 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 216
    [win=0x200003c canvas=0x200003c 0 NoExpose] 216 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 215
    [win=0x200003c canvas=0x200003c 0 NoExpose] 215 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 214

    Yeah, it's sucks and it's hard to read. But, as you can see, when
    select_form_event() processes an event that is intended for the canvas, it
    returns 0 which causes that event to be put back in the queue by
    get_next_event(). This documentation taken from the Xlib reference manual
    tells why the is happening with XCopyArea only (apparently it would also
    happen with XCopyPlane):

    "If graphics_exposures is True in the GC used for the copy, either one
    NoExpose event or one or more GraphicsExpose events will be generated for
    every XCopyArea or XCopyPlane call made."

    One interesting thing I noticed, which you can see in the above log
    snippet, is every time the event queue increases in size, it increases by
    exactly 100 events and this increase happens every 100 events. The only
    exception is just after the test program starts, when the event queue is
    rising to it's peak of around 300 events (the increases happen at the same
    frequency, but the increase is by 120-130 events). This probably has
    something to do with the way events are queued or read when they start
    coming in real fast. Aside from the relatively few expected form events,
    they are all NoExpose events directed to the canvas.

    The initial rise of the number of events in the event queue supports my
    point about an event not being handled every 11th call to
    get_next_event(). It takes too long for me to paste the log file in, but
    what happens is it starts out around 1, then increases slowly, one event
    at a time (as the backlog builds up because every 11th call to
    get_next_event() ignores an event. Eventually the increases start
    happening in jumps, but like I said, this is probably a side effect of the
    delay, or some other weird thing that doesn't really matter. Here is a
    part of the log that shows the initial growth of the event queue:

    [win=0x200003c canvas=0x200003c 0 NoExpose] 1 1 TO WATCH
    IO!
    [win=0x200003c canvas=0x200003c 0 NoExpose] 1 [win=0x200003c
    canvas=0x200003c 0 NoExpose] TO WATCH IO!
    [win=0x200003c canvas=0x200003c 0 NoExpose] 2 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 1
    [win=0x200003c canvas=0x200003c 0 NoExpose] 2 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 1
    [win=0x200003c canvas=0x200003c 0 NoExpose] 1 [win=0x200003c
    canvas=0x200003c 0 NoExpose] TO WATCH IO!
    [win=0x200003c canvas=0x200003c 0 NoExpose] 2 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 1
    [win=0x200003c canvas=0x200003c 0 NoExpose] 2 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 1
    [win=0x200003c canvas=0x200003c 0 NoExpose] 1 [win=0x200003c
    canvas=0x200003c 0 NoExpose] TO WATCH IO!
    [win=0x200003c canvas=0x200003c 0 NoExpose] 2 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 1
    [win=0x200003c canvas=0x200003c 0 NoExpose] 2 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 1
    [win=0x200003c canvas=0x200003c 0 NoExpose] 1 [win=0x200003c
    canvas=0x200003c 0 NoExpose] TO WATCH IO!
    [win=0x200003c canvas=0x200003c 0 NoExpose] 2 2 TO WATCH
    IO!
    [win=0x200003c canvas=0x200003c 0 NoExpose] 2 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 1
    [win=0x200003c canvas=0x200003c 0 NoExpose] 3 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 2
    [win=0x200003c canvas=0x200003c 0 NoExpose] 2 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 1
    [win=0x200003c canvas=0x200003c 0 NoExpose] 3 [win=0x200003c
    canvas=0x200003c 0 NoExpose] 2

    It is very hard to read, I know, because of the line breaks. But you can
    see how it starts to build up.

    So I've come to the conclusion that what is happening is that events are
    not removed from the queue fast enough by get_next_event(), because an
    event gets ignored every once in a while. Additionally, get_next_event()
    incorrectly proceeds to fl_watch_io() with events still in the queue,
    which causes fl_watch_io() to hang as that source comment indiciates it
    should.

    I can think of a number of solutions but I'm not sure which one is correct
    with the least bad side effects:

    1) Make select_form_event() ignore NoExpose events. Bad because: This is a
    hack, it's not what select_form_event() is supposed to be doing.
    2) Make get_next_event() ignore NoExpose events right after the call to
    XNextEvent, and keep calling XNextEvent until either no events are left or
    a different event type is received. Good because: This is an appropriate
    place to do that.
    3) Don't set graphics_exposures to True in the GC, so that NoExpose events
    are never generated. Good because: Cuts down on the overhead of receiving
    and ignoring NoExpose events, and is as low level as possible a way of
    stopping these events.
    4) Make get_next_event() keep taking in events until there aren't any
    before the fl_watch_io() call. Bad because: Some events won't be handled,
    since the dispatching is done in do_interaction_step(), not in
    get_next_event(). This looping could go on for a long time if lots of
    events come in.
    5) Remove the fl_watch_io() stuff from get_next_event(), and put it in
    do_interaction_step(). Then, make do_interaction_step() loop and handle
    xevents until their are none in the queue, and only call fl_watch_io()
    after that is done. Good because: All events get handled. Bad because:
    This starts to defeat the purpose of using fl_check_forms() instead of
    fl_do_forms().
    6) Move the fl_watch_io() stuff into do_interaction_step() like in #5, but
    instead of looping, make it do this: Every 11th call, skip event
    processing and call fl_watch_io(). On the *next* call, process and handle
    2 events instead of 1. Good because: events get handled, no looping. Bad
    because: If two different objects end up getting the FL_* event, which one
    should fl_check_forms() return?
    7) Make it so that fl_watch_io() still gets called every 11th call, *but*
    an event still gets received (never skip event processing). After the
    event is received, it will be removed from the queue. If there's still
    some events left in the queue by the time fl_watch_io() is called, then
    too bad... 1 or 2 events are better than 300 of them.

    Most of these are based on the observation that do_interaction_step() does
    nothing with NoExpose and GraphicsExpose events; they end up getting
    passed along to the form as FL_OTHER. But I haven't looked at the canvas
    code close enough to see if it does anything with these.

    I like solution 3, but then the problem still remains with the every 11th
    event being skipped thing. Solution 7 seems OK to me, too, because it is
    very, very simple.

    I tried solution 7, it was implemented very easily. It worked perfectly
    and resulted in fl_watch_io() being called with a single event in the
    queue about only 5% of the times it was called, even during periods of
    lots of activity. No more than 3 messages were in the queue at any given
    time.

    So, my conclusions on this are that I suggest one of two possible fixes to
    this problem: Solution 7 (very easy, no side effects) and solution 3
    (haven't tried it). Does anybody have any thoughts as to what would be the
    most appropriate? Are NoExpose and GraphicsExpose events ever really
    needed by the forms library?

    Jason

    _________________________________________________
    To unsubscribe, send the message "unsubscribe" to
    xforms-request@bob.usuhs.mil or see
    http://bob.usuhs.mil/mailserv/xforms.html
    XForms Home Page: http://world.std.com/~xforms
    List Archive: http://bob.usuhs.mil/mailserv/list-archives/
    Development: http://savannah.nongnu.org/files/?group=xforms



    This archive was generated by hypermail 2b29 : Wed Apr 23 2003 - 02:19:56 EDT