Re: Doubts about GPeriodic



Hi,

On Fri, Oct 22, 2010 at 10:28 AM, David Zeuthen <zeuthen gmail com> wrote:
> If you believe that the GUI thread should never perform blocking IO
> (such as reading from disk or IPC) or never perform CPU-intensive
> tasks (such as image- or video-decoding) then... then all that your
> code in the GUI thread does, is to receive data from one thread and
> maybe signal another thread.

This point only affects the "constant factor" though right, not the
basic character of what's going on.

If I have a spinner animation and that paints flat-out as fast as
possible without a "yield gap" to let other sources run, then that
_also_ starves a superfast main loop source that just sits there
grabbing messages and then throwing them elsewhere, just as much as it
starves a super slow main loop source. Speed is not the problem, it's
whether the source runs at all.

If you go the other way and want to starve painting if we're doing our
fast message throwing, then you're relying on always processing
messages faster than the other side can send them. Being "fast" is not
enough; it has to be "faster," i.e. it has to catch up and empty the
queue. In fact *all* active main loop sources have to happen to be
caught up *on the same iteration*. So if you're emptying three queues
you have stay ahead of all three senders at once and get them all to
zero at the same moment, and only then can you paint.

There's no special guarantee you can do that. You're relying on it
happening to work out.

Imagine two processes that are both following the rules and have 10
streams open to each other and they are both processing all 10 at a
superfast rate just tossing messages back and forth. What's the
latency between occasions where these processes have 0 sources to
dispatch? That drives your framerate. While 10 streams between two
apps sounds contrived, I don't think one big complex app with say a
sound server and some downloads in the background and some other
random main loop tasks is all that different.

> Anyway, my point really was something like this: If you want to talk
> about smooth animations and synchronoizing to vblank, it would
> probably be good for GPeriodic, Clutter and GTK+ to specify what
> people should and shouldn't be doing in the "GUI Thread".... I know a
> lot of it is obvious to people on this list but it never hurts to
> write it down anyway.

With my "finite-length yield gap in the paint loop" approach, I think
you can do anything in the GUI thread as long as each single dispatch
is fast (and bounded in time). So you can't block, but you can do
anything that is _always_ pretty fast (you can't do things that are
_usually_ pretty fast, such as drain an unbounded queue, or blocking
IO that sometimes decides to hang for a bit).

That's how I'd document it.

The one thing that still breaks is if all your fast-dispatching
GSource add up to not-fast, since we have to dispatch all or nothing
at each priority. Solving that could be overkill though. File under
"someday."

With a yield gap, you need threads to block or to do an indivisible
long computation, but you don't need threads just because you have a
queue (or a divisible computation, which is basically a queue).

In the more classic approach (paint priority stays constant regardless
of time elapsed), I think you can do anything in the GUI thread as
long as:
- each individual dispatch is fast AND
  - (an animation is allowed to starve whatever you are doing
indefinitely so you can be below paint priority OR
  -  the sum of all dispatches that could occur in a single frame
timespan is fast and bounded. No queues. Long computations are no good
even if split up across dispatches. So you can be above paint
priority.)

it isn't clear that all long, but divisible, computations can be
tossed out of the UI thread. "filling a Tree/TextView" is a good
example of how "UI" vs. "not UI" is kinda fuzzy....

To avoid queues in the main UI thread, you need both source and sink
to be threadsafe, and real-world unthreadsafe sources include say
libdbus, real-world unthreadsafe sinks include say GtkWidget.

One thing, it doesn't matter if paint priority is default or idle. The
issue is created when it's fixed with respect to "other stuff,"
instead of changing priority dynamically.

Anyway, yes, this only matters for a large complex app doing lots of
stuff in the same process as painting, while also trying to avoid
dropping frames. For any simple case, things just muddle through.

Havoc


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