[comp.sys.mac.system] Preemption good, time-slicing bad

ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) (04/01/91)

In article <7618@idunno.Princeton.EDU>, bskendig@set.Princeton.EDU
(Brian Kendig) says:

"Do you want to open up MacWrite II, SuperPaint, HyperCard, and a few
other applications, then have your work in Microsoft Excel be slowed
to a crawl as your Macintosh takes time out every few milliseconds to
make sure MacWrite II hasn't suddenly developed a need to do something?
Preemptive multitasking means that the more applications you have open,
the slower your machine will go..."

I'd like to clarify a couple of things here:

* "Preemptive" multitasking means that, if a task becomes ready to
  run, and the task that's already running is _lower_ in priority, then
  the former can immediately grab the CPU away from the latter.
* If the OS goes one step further, so that a running task is periodically
  forced to give up the CPU to another waiting task of the _same_
  priority, then this is called "time-slicing".

I think preemptive multitasking is a good idea, in both single-user
and multi-user systems. It makes many things simpler (and improves
responsiveness) for both programmers and users.

Multi-user OSes use time-slicing as one technique to ensure that no
user can hog the whole system at the expense of others. In a single-
user system, where you have multiple tasks cooperating, rather than
competing, with each other, I think time-slicing is a poor idea.

Brian Kendig seems to believe that preemptive multitasking systems
also have to do time-slicing. I'd like to make it clear that this is
not the case.

Lawrence D'Oliveiro                       fone: +64-71-562-889
Computer Services Dept                     fax: +64-71-384-066
University of Waikato            electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand    37^ 47' 26" S, 175^ 19' 7" E, GMT+12:00
DOS 2.0: still the biggest jump in functionality in DOS's history.

time@ice.com (Tim Endres) (04/01/91)

In article <1991Apr1.221924.3287@waikato.ac.nz>, ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) writes:
> In article <7618@idunno.Princeton.EDU>, bskendig@set.Princeton.EDU
> (Brian Kendig) says:
> 
> "Do you want to open up MacWrite II, SuperPaint, HyperCard, and a few
> other applications, then have your work in Microsoft Excel be slowed
> to a crawl as your Macintosh takes time out every few milliseconds to
> make sure MacWrite II hasn't suddenly developed a need to do something?
> Preemptive multitasking means that the more applications you have open,
> the slower your machine will go..."
> 
> I'd like to clarify a couple of things here:
> 
> * "Preemptive" multitasking means that, if a task becomes ready to
>   run, and the task that's already running is _lower_ in priority, then
>   the former can immediately grab the CPU away from the latter.
> * If the OS goes one step further, so that a running task is periodically
>   forced to give up the CPU to another waiting task of the _same_
>   priority, then this is called "time-slicing".

And also remember, under UNIX (with pre-emptive multitasking), a process
does NOT get CPU time unless it is ready to run. Thus, processes waiting
for input or I/O don't waste "idle" time.

The problem, in the Macintosh case, is that processes do not "block"
like UNIX processes, they "event loop". This is why the majority of
open programs *will* be taking CPU time, and why it will be less
efficient. I am not sure if or how Apple addressed this under A/UX,
but I believe it was a tough problem.

-------------------------------------------------------------
Tim Endres                |  time@ice.com
ICE Engineering           |  uupsi!ice.com!time
8840 Main Street          |  Voice            FAX
Whitmore Lake MI. 48189   |  (313) 449 8288   (313) 449 9208

doner@henri.ucsb.edu (John Doner) (04/02/91)

In article <1CE00001.bmpkbkz@tbomb.ice.com> time@ice.com writes:
>And also remember, under UNIX (with pre-emptive multitasking), a process
>does NOT get CPU time unless it is ready to run. Thus, processes waiting
>for input or I/O don't waste "idle" time.
>
>The problem, in the Macintosh case, is that processes do not "block"
>like UNIX processes, they "event loop". This is why the majority of
>open programs *will* be taking CPU time, and why it will be less
>efficient. I am not sure if or how Apple addressed this under A/UX,
>but I believe it was a tough problem.

When it's time to consider doing a switch, the decision must be made
as to whether a process is "ready to run."  This decision must be made
either by the operating system, as with UNIX, or by the process
itself, as with the Mac.  Either way, some cycles are going to be
spent making the decision, so it's problematic which method is more
efficient, whether inherently or potentially.  As to the "event loop"
in a Mac application, note that for most Mac applications, handling of
a null event is an extremely brief process (with the exception of
programs maintaining some sort of continuously visible activity, such
as a clock; and in those cases, even a pre-emptive multitasking OS
must give them time).

I don't believe the current Mac OS allows for priorities among running
processes, but I don't see any reason why this feature couldn't be
implemented.  It's simply a matter of withholding events from the
application until the OS decides to release them.

Despite what I've said, I too would like to see a pre-emptive
multitasking Mac OS.  It's just that I'm in less of a hurry to get it,
and I don't believe it will have as much benefit as many people seem
to think.

John E. Doner	doner@henri.ucsb.edu	(805)893-3941
Dept. Mathematics, UCSB, Santa Barbara, CA 93106

tagreen@bronze.ucs.indiana.edu (Todd A. Green) (04/02/91)

In article <10227@hub.ucsb.edu> doner@henri.UUCP (John Doner) writes:
>In article <1CE00001.bmpkbkz@tbomb.ice.com> time@ice.com writes:
> [articles debating multitasking deleted]
>
>I don't believe the current Mac OS allows for priorities among running
>processes, but I don't see any reason why this feature couldn't be
>implemented.  It's simply a matter of withholding events from the
>application until the OS decides to release them.
>

I concur that right now there is no way for the user to give a program
priority, but since when you call WaitNextEvent() you pass as one of
its arguments a value that will tell your app how many ticks you are
willing to give up before gaining the cpu back, I don't see why it
would be that hard to implement this.

I'm still relatively new at programming the Mac, but wouldn't this
seem like a logical solution: You can declare your sleep time
parameter to be a variable and then give the user a way of changing
the amount of ticks that s/he wants the application to give up. (At
least it's one that I've put into all my (whopping 4 ;) ) programs
I've written.  This could be in the form of a slidebar in a dialog
box, a simple pull down menu item, or whathaveyou.  Now wouldn't it be
even better (IMO) if Apple where to implement this at the system
level, say perhaps when you called "About the Finder" (or it could
have it's own dialog box) instead of just giving you the apps that are
running, their memory usage etc., you also had an option to change the
amount of ticks the apps would give up.  This way there would be a
common interface for developers and users alike.  A macintosh version
of the "nice" command in Un*x.

Also on another side note, someone said earlier that all programs that
are running in the background get the same amount of time, yet no one
contested it.  This is not true as I understand it, and would really
like to be corrected if I am wrong. (Probably should go home and read
IM again...but I do have that Portuguese paper due *sigh* ).  It's my
understanding that apps in the "background" get a time slice and then
perform whatever routines they want and then release the cpu again.
Thus if I check for context switching (via app4 event right?) and see
that I've been switched out to the background I can be a "nice"
programmer and change my sleep parameter to give up say 10 ticks
before trying to regain the cpu, whereas when I get switched back into
the foreground (and yes I know this language is vague and there are
different kinds of context switches, but I hope I've made myself
clear) then I can use more cpu time setting my sleep value to 0L,
since I am the application that would probably need the most
attention.  Of course this depends on exactly what type of application
you are writing etc...but these are just general thoughts.  My main ?
is that even though you've been switched out that does not mean that
all of a sudden you get the same amount of time as all other apps
correct?

Todd
-----
Internet:
tagreen@bronze.ucs.indiana.edu
NeXTMail:
tagreen@lothario.ucs.indiana.edu

lsr@Apple.COM (Larry Rosenstein) (04/02/91)

In article <1CE00001.bmpkbkz@tbomb.ice.com> time@ice.com writes:
>
>
>The problem, in the Macintosh case, is that processes do not "block"
>like UNIX processes, they "event loop". This is why the majority of

This isn't true.  Programs can specify (in their calls to WaitNextEvent) the
conditions under which they need the CPU.  Until one of those conditions is
met, the program takes no CPU time.  

The conditions are expressed in the form of: (1) a set of event types in
which the program is interested, (2) a screen region for tracking the mouse,
and (3) a timeout.  If the mouse region is specified, MultiFinder will
generate a mouse moved event if the mouse is outside the region.  This is
used so the application can change the cursor shape.  The timeout is used
for periodic actions such as blinking the insertion point.

Assuming that programs pass the right values to WaitNextEvent, then they
don't take any CPU time unless they have something to do (process an event,
change the cursor shape, blink the insertion points, etc.).



-- 
		 Larry Rosenstein,  Object Specialist
 Apple Computer, Inc.  20525 Mariani Ave, MS 3-PK  Cupertino, CA 95014
	    AppleLink:Rosenstein1    domain:lsr@Apple.COM
		UUCP:{sun,voder,nsc,decwrl}!apple!lsr

woody@truebalt.caltech.edu (William Edward Woody) (04/02/91)

After following this thread, I thought I'd post an interesting solution I
came up with for a compute-bound application which needs to work in the
background.  This uses the existing Macintosh calls (GetNextEvent, in
particular), and seems to work.

Of course I'm typing this solution off the top of my head, and I think I
may get some of the facts wrong.  However, I think I got most of it right.

Suppose you have a compute-bound task that executes in one or more loops.
One reasonable thing you may want to do is to display a window giving the
current status of the computation, and another would be to yield control
as soon as an event occured in another application.  This would allow the
user (for example) to run his word processor program and yet allow your
program most of the CPU time.

My solution involves creating a 'status display' routine which updates
the status window with some figure giving a measure of the amount of work
thus done.  The algorithm works something like this:

	int oldval;
	int newval;		/* Globals */
	long lastTime;

	UpdateStatus(int value)
	{
	    newval = value;	/* Stash new status value away */
	    if (lastTime + GetDblTime() < TickCount()) {
		DrawNewStatus(oldval,newval);
		oldval = newval;
		GetNextEvent(everyEvent,&e);
		lastTime = TickCount();
		if (IsCancel(&e)) AbortProgram();
	    }
	}

The principle part of this algorithm is to simply stash away the status
value away in a global variable and return immediately if a 'delta'
time (I used GetDblTime() in this example) hasn't passed.  This makes this
function have as little overhead as possible, so it can be called as
often as possible.

When an event occures, the user winds up waiting for a short period of
time (a double-click time is about a tenth of a second), but then he
gets control.  If this is the background application, Multifinder will
eventually pass control back to this routine as soon as the frontmost
application stops receiving events.

I keep both the 'oldval' and 'newval' globals as I usually draw a filled
rectangle to indicate the amount of computation that has elapsed, and
only fill the portion of the rectangle which has actually changed.

In imperical testing, I have noticed that when run by itself as a background
task, I seem to get about 95% of the CPU.  When I use a text editor in the
foreground the text editor doesn't seem to hesitate, as the tenth of a
second delay is just below my 'pain threshhold', and of course once the
foreground application is receiving events, it is not swapped out in favor
of the background application until the foreground stops receiving events
for some amount of time.

It is much nicer than the way MPW's C compiler seems to allow itself to
swap out; I've noticed up to a quarter of a second to a half a second delay
(sometimes even longer) before the foreground application starts noticing
events.

See, you don't have to have pre-emptive multitasking to make a good system
work well; you just have to think about the problem a tiny bit longer.

						-- Bill

-- 
	William Edward Woody		   | Disclamer:
USNAIL	P.O.Box 50986; Pasadena, CA 91115  |
EMAIL	woody@tybalt.caltech.edu	   | The useful stuff in this message
ICBM	34 08' 44''N x 118 08' 41''W	   | was only line noise. 

n67786@cc.tut.fi (Tero Nieminen) (04/02/91)

In article <1991Apr1.232302.6882@bronze.ucs.indiana.edu> tagreen@bronze.ucs.indiana.edu (Todd A. Green) writes:

   I concur that right now there is no way for the user to give a program
   priority, but since when you call WaitNextEvent() you pass as one of
   its arguments a value that will tell your app how many ticks you are
   willing to give up before gaining the cpu back, I don't see why it
   would be that hard to implement this.

   I'm still relatively new at programming the Mac, but wouldn't this
   seem like a logical solution: You can declare your sleep time
   parameter to be a variable and then give the user a way of changing
   the amount of ticks that s/he wants the application to give up. (At
   least it's one that I've put into all my (whopping 4 ;) ) programs
   I've written.  This could be in the form of a slidebar in a dialog
   box, a simple pull down menu item, or whathaveyou.  Now wouldn't it be
   even better (IMO) if Apple where to implement this at the system
   level, say perhaps when you called "About the Finder" (or it could
   have it's own dialog box) instead of just giving you the apps that are
   running, their memory usage etc., you also had an option to change the
   amount of ticks the apps would give up.  This way there would be a
   common interface for developers and users alike.  A macintosh version
   of the "nice" command in Un*x.

Only partly and unfortunately in an improper order. Of cource programs
that are idling can call it with a big enough value never to be called
again due to this timing coming to end. But in the case of an active
process it is a lot uglier to decide for how long this particular
process thould be given cpu time before it return to give time to other
processes, which is most probably what you'd want anyway in order to
prevent sluggishness. Now it's often not at all that easy to estimate
how long a process is going to take to finnish should you call it
periodically in the spoken process. Think for example an iterative
process. Are you going to call WaitNextEvent every time (no waste of
time due to relatively slow context swithing of the MF) or do you
maintain a separate time-slice-variable that when it reaches certain
value you reset it and call WaitNextEvent (this might be more
efficient). You might also want to rotate some cursor or something
during theese times. Also this kind of fiddling would be needed with
recursive proceduress, allbeit one more level of programming is needed
to hold this time-slice-variable. Also it makes general purpose
libraries somewhat annoying to write, since you have to insert this kind
of callback in every library procedure that might consume enough time to
cause sluggishness. If MF instead had preemptive multitasking with time
slicing all this hassle would be taken care by the scheduler of the OS.
But it's not at all that easy to provide such scheduler into MF since
the Mac OS wasn't designed that way and it brings a lot of grief to make
it work. When all this was combined with a clever prioritizing scheme
that would give interactive processes relatively high priority to
produce faster responses to user actions, what more could we hope for.
But as the Mac OS being what it is, this might prove to be more than
difficult to achieve, which is sad. I guess the original designers of
the Macintosh didn't forsee this kind of need and so didn't prepare for
it, so that now apple has to be making all kinds of excuses why they are
not making it. The designers of the Amiga did see this, but their
implementation is still far from the capabilities of a unix system,
which is good refrence point.

   Also on another side note, someone said earlier that all programs that
   are running in the background get the same amount of time, yet no one
   contested it.  This is not true as I understand it, and would really
   like to be corrected if I am wrong. (Probably should go home and read
   IM again...but I do have that Portuguese paper due *sigh* ).  It's my
   understanding that apps in the "background" get a time slice and then
   perform whatever routines they want and then release the cpu again.
   Thus if I check for context switching (via app4 event right?) and see
   that I've been switched out to the background I can be a "nice"
   programmer and change my sleep parameter to give up say 10 ticks
   before trying to regain the cpu, whereas when I get switched back into
   the foreground (and yes I know this language is vague and there are
   different kinds of context switches, but I hope I've made myself
   clear) then I can use more cpu time setting my sleep value to 0L,
   since I am the application that would probably need the most
   attention.  Of course this depends on exactly what type of application
   you are writing etc...but these are just general thoughts.  My main ?
   is that even though you've been switched out that does not mean that
   all of a sudden you get the same amount of time as all other apps
   correct?

But since the mac is a cooperative multitasking system no matter how
small you set the time slice you won't gain time before other processes
have given up their right to take what they want. If, on the other hand,
this time slice had a stronger impact on processes currently running the
OS would interrupt the time hogger and give a time slice to other
processes too. But there it goes. The dreaded "interrupt time".
Currently it would not be possible to just interrupt a process and give
time to others since the running process might be in a middle of a heap
relocating process during which several activities by programs are
strictly forbidden. We would need away to eiher prevent time slice
interrupts during such moments (which probably could be cludged into
the Mac OS) or redesign the memory allocator to allow such interrupts to
occur (you know some process might be in a middle of allocating a HUGE
memory block, which we don't want to wait to finnish). But all in all
this would make just more mess into the OS. In practice it would need to
be redesigned in a clean way, which is why it hasn't been done yet.
Eventually, one way or the other, it will.

-- 
   Tero Nieminen                    Tampere University of Technology
   n67786@cc.tut.fi                 Tampere, Finland, Europe

dorner@pequod.cso.uiuc.edu (Steve Dorner) (04/02/91)

In article <1991Apr2.055242.21143@nntp-server.caltech.edu> woody@truebalt.caltech.edu (William Edward Woody) writes:
>See, you don't have to have pre-emptive multitasking to make a good system
>work well; you just have to think about the problem a tiny bit longer.

Well, almost.  EVERYBODY has to think about the problem a tiny bit longer,
or you're sunk.  How is you or I thinking about the problem a tiny bit
longer for our apps going to fix Apple's C compiler?

The weakness of the current system is that it requires EVERY program to
behave in exactly the correct manner.  Protected, preemptive systems are
much more tolerant of flaws.

(Am I STILL in this argument?  I must have lost my mind...)
--
Steve Dorner, U of Illinois Computing Services Office
Internet: s-dorner@uiuc.edu  UUCP: uunet!uiucuxc!uiuc.edu!s-dorner

dorner@pequod.cso.uiuc.edu (Steve Dorner) (04/02/91)

In article <1991Apr1.232302.6882@bronze.ucs.indiana.edu> tagreen@bronze.ucs.indiana.edu (Todd A. Green) writes:
>Thus if I check for context switching (via app4 event right?) and see
>that I've been switched out to the background I can be a "nice"
>programmer and change my sleep parameter to give up say 10 ticks

What if the service you're performing is vital to the user, and it wants you
to have as much cpu as you need, background or not?  What if NOTHING at all
is going on in the foreground, except the user twiddling its thumbs, waiting
for you to finish, (and staring at inane news articles :-))?  Why make it
wait longer than it must?

A priority system of some sort would be a help.  How much difference it
would make to most users is very doubtful; most users don't do much multi-
tasking anyway, or so I think.

(On to Moscow!)
--
Steve Dorner, U of Illinois Computing Services Office
Internet: s-dorner@uiuc.edu  UUCP: uunet!uiucuxc!uiuc.edu!s-dorner

tagreen@bronze.ucs.indiana.edu (Todd A. Green) (04/02/91)

In article <1991Apr2.144318.4117@ux1.cso.uiuc.edu> dorner@pequod.cso.uiuc.edu (Steve Dorner) writes:
>In article <1991Apr1.232302.6882@bronze.ucs.indiana.edu> tagreen@bronze.ucs.indiana.edu (Todd A. Green) writes:
>>Thus if I check for context switching (via app4 event right?) and see
>>that I've been switched out to the background I can be a "nice"
>>programmer and change my sleep parameter to give up say 10 ticks
>
>What if the service you're performing is vital to the user, and it wants you
>to have as much cpu as you need, background or not?  What if NOTHING at all
>is going on in the foreground, except the user twiddling its thumbs, waiting
>for you to finish, (and staring at inane news articles :-))?  Why make it
>wait longer than it must?

Actually I've been meaning to learn how the Event queue is "stored".
I'm not skilled enough (yet) to take a peak at it.  Ideally (at least
for now till I come up with a better solution or hear a better one),
I'd like to look at the event queue record and see how many null
events are stored, and base the amount of time my background app would
use on this; _if_ this is how it works.  Thus if I could tell that the
other apps were just processing null events I could start crunching
away, but if I noticed that the forground app was processing keydown's
I'd slow it down. Hmm...time to hit the ole IM again. Anyone who would
care to share their infinite wisdom on the workings of the event queue
is welcome :) (via email if people are truly sick of this thread)
 
>A priority system of some sort would be a help.  How much difference it
>would make to most users is very doubtful; most users don't do much multi-
>tasking anyway, or so I think.

I could not live without a multitasking machine.  I only wish I had
more hands (perhaps a brain would help too ;) ). Actually the virtual
reality ports on the Mac III should help.

>(On to Moscow!)
>--
>Steve Dorner, U of Illinois Computing Services Office
>Internet: s-dorner@uiuc.edu  UUCP: uunet!uiucuxc!uiuc.edu!s-dorner

(On to Rio!!!)

Todd
-----
Internet:
tagreen@bronze.ucs.indiana.edu
NeXTMail:
tagreen@lothario.ucs.indiana.edu

ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) (04/06/91)

In article <12895@goofy.Apple.COM>, rmh@apple.com (Rick Holzgrafe) writes:

"Pre-emptive multi-tasking is a good scheme [on a multi-user system],
to guarantee that each competing user gets a slice of the CPU's pie."

Here we go again...

It's not preemption per se that guarantees that competing users get
a fair share of CPU time: it's time-slicing. Everybody repeat after me:
"you *can* have priority preemption without time-slicing".

Sorry to be such a bore. It was my posting which first tried to make
clear this distinction, which started the subject line for this thread.

Lawrence D'Oliveiro                       fone: +64-71-562-889
Computer Services Dept                     fax: +64-71-384-066
University of Waikato            electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand    37^ 47' 26" S, 175^ 19' 7" E, GMT+12:00
It's all very well being reasonable, but it helps to get your own
way once in a while.