Changes acceptance and polling issues

Lex Spoon lex at
Mon Jan 29 07:41:24 UTC 2001

> I don't really think I agree with this. These kinds of operations are by
> their very nature "multi tasking". I/O *should* be processed behind the
> scenes IMO. And since the focal point of IPC is very clearly definable,
> complexity isn't much of an issue. There is the queue out outgoing messages
> that is shared, and there is the incoming message dispatching. Protecting
> access to the output queue is trivial. For incoming messages, there's a
> design issue of wheather to process messages in a separate event process or
> let the calling code provide the process (or something else entirely).

The incoming messages are precisely the hard part.  Those guys will make
big changes to the model, and they'll trigger UI updates.  How do you
manage these changes, if the messages are being processed outside of the
UI thread?  You either have to put locks everywhere -- meaning you
always wonder whether you have the locks set up correctly -- or you have
to explicitly forward the updates over a message queue  -- meaning you
have to work out an object model for the updates.

The single-threaded version doesn't have these concerns.

> But it's not a major block in the road IMO. For my Java IRC implementation
> I opted to use an event dispatching thread to handle events in a listener
> pattern fashion because I thought it was the obvious choice. It never even
> occurred to me to use some kind of polling API :)

In the code in question, there is just one polling loop; the rest of the
code is driven via direct method calls and on event broadcasts.  The
vast simplification is that none of the code worries about
synchronization; the message handlers can just update the model and call
#changed: directly.

> Maybe I'm in the minority. But I've never really had a problem with
> multithreading; as far as I can recall I've never ran into a deadlock
> bug for example. IMO the advantages by far outweight the disadvantages.

Well, I don't have much personal experience with this, either.  Then
again, I tend to write sequential code!  I can give three examples of
other peoples' code with threading problems, though, in increasing order
of vagueness:

	1. The Windows Squeak VM and its handling of sockets.  Each socket gets
at least one thread, and I've been told that socket shutdown, for
example, is extremely complicated.

	2. The sophomore class I'm an assistant for is using Squeak, and the
newsgroup has several posts from people whose images are locked up. 
>From the descriptions, it sounds like threading errors to me -- one busy
loop at a high priority, and bye bye image.

	3. The lore of both CS departments I've spent time in is that it's
risky to log into department machines when students have threading
assignments -- the machines tend to fill up with processes and lock up.

I can also argue this from principle, too, but I won't bother unless
requested.  Surely most people agree that threads are error prone, and
that the errors they generate tend to be hard to track down.

> > Second, there are cases where polling doesn't have the ills that are
> > usually ascribed to it.  In particular, polling works well when failed
> > polls are cheap, and where polls can happen infrequently.  If a problem
> > meets both of these criterea, then polling will work fine.  CPU usage
> > will not be abnormally high, and responsiveness will be good.  IRC meets
> > both criteria, while HTTP serving probably does not. 
> This might be acceptable in practice. I'm a purist though; I don't like
> polling as a matter of principle unless there's a *really* good reason for it
> (such as implementing a progress bar when you don't want to trigger an update
> after each I/O operation).
> At the moment I have Squeak running an IRC bot on a server. It constantly
> hogs about 0.5-2% of the CPU - probably because I'm invoking processIO four
> times per second.

So you are claiming that the CPU usage is actually significant?  I
disagree, and provide two arguments.  First, the CPU load in Squeak is
typically a couple of percentage points anyway, even *without* IRC
running.  Second, the following code is a direct timing of the polling

  c := IRCConnection new.
  c openView.
  "connect to a server and wait for initial messages to go by"
  [ 1000 timesRepeat: [ c processIO. ] ] timeToRun "40"

40 milliseconds for 1000 polls is not a CPU drain.  And note, this code
hasn't had any time devoted to optimization -- there is probably room
for improvement, should it ever become a concern!  Furthermore, note
that when the IRC connection gets busy, the overhead goes *down*; in the
extreme case where every poll finds work to do, the overhead is *less*
than that of threading plus synchronization.

Overall, if you argue from purity, then there is little I can say.  If
we talk about concrete measures, however. it seems that avoiding threads
 will make this system simpler, it will avoid some hard bugs, and it
won't significantly affect performance.


More information about the Squeak-dev mailing list