DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T c

⟦1b5d528c6⟧ TextFile

    Length: 7529 (0x1d69)
    Types: TextFile
    Names: »cpu.speedup«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/news/uucp/cpu.speedup« 

TextFile

Under certain circumstances, you may find that when 2 or 3 uucicos
are running on your system, they are eating up all the CPU time,
and system performance suffers horribly.  If this is your problem,
you can do a "vmstat 5" and watch the system calls and context switches
counters.  If they are both very high whenever 2 or more uucicos
are running (100-200 system calls/second, over 100 context switches),
chances are that the problem is as follows:

When another system is sending you a file, your uucico reads characters
from the line.  The read returns whatever is there waiting, or if
nothing is waiting, waits for one character and returns.  Since uucico
usually wants 64 characters at a time, at 1200 baud it's quite common
to read these in 1 or 2 character pieces.  Each uucico will read 1 or
2 characters, wake up the user process, go back for more, there won't
be any, so it hangs and gives up the CPU.  A very short time later,
(often within the same clock tick) there will be a character available,
the process will wake up, read one character, and try again.

This modification is very simple.  If the first read returned fewer
characters than requested, before doing another read, the process
will sleep for one second.  Then, when it wakes up, there will probably
be as many characters waiting as it needs.

This modification makes a big difference when you are RECEIVING a file
from another system.  It won't make much difference when you are
SENDING a file, because the user process doesn't usually have to hang
to write to the line, and when it does, the high/low water mark
mechanism in the tty driver keeps it from waking up too often.
This change is intended for a V7 or 4BSD system.  It may not
help much on System V, because uucp uses a USG tty driver feature
to make it wake up only every 6 characters.

The amount this fix helps depends a LOT on the baud rate.  Since it
is sleeping while it had been reading characters, it is reasonable
to expect the file to get transferred more slowly than before.  This
might, in turn, lead to increased phone bills.  Some experimentation
receiving a file over a hardwired link is detailed here.  The file
received is /etc/termcap, which is 66405 bytes long.  The local system
is a 4.1BSD VAX 11/750, the remote system is a UNIX 5.0 VAX 11/750.
The link is over a develcon dataswitch.  Both systems were almost
idle, although when another uucico did start up, it didn't seem to
affect the numbers.  The commands
	uucp -r othersys!~/termcap ~uucp/termcap
	time /usr/lib/uucp/uucico -r1 -sothersys
were given.

"type" is the type of uucico run: "old" is without the sleep, "sleep"
has a sleep(1) added after every short read, "nap" is the same as
sleep except that at 4800 baud and higher the sleep is for less than
one second (the parameter is the number of milliseconds).  "user" and
"sys" are the user and system CPU times from the time command, in
seconds.  "elapsed" is the time, in seconds, to transfer the file,
taken from /usr/spool/uucp/SYSLOG.  (Elapsed time does not include time to
get the connection going or close it down, just to transfer the file.)
"%" is the percentage of the system the uucico command took, from the
time command.

type	speed	user	sys	elapsed	%

old	1200	35.3	120.8	606	21%
sleep	1200	14.2	 35.9	609	 7%

old	2400	27.4	115.8	305	31%
sleep	2400	13.2	 35.0	351	 9%

old	4800	23.9	116.0	152	57%
sleep	4800	14.4	 40.3	338	12%

old	9600	14.4	 68.1	79	42%
nap 60	9600	14.6	 52.7	97	39%
nap 100	9600	14.9	 48.5	113	32%
nap 200	9600	15.0	 47.1	127	37%
sleep	9600	12.0	 46.1	279	15%

It is clear that at 2400 baud or less, the load on the system was
cut considerably, while the penalty in slower transfer speed is
negligible.  At 9600 baud, the sleep version (equivalent to nap 1000)
cut the system load by about 1/3, the elapsed time shot way up.
(It takes much less than 1 second to accumulate 64 characters at
9600 baud.) At 4800 baud the results are somewhere in between.
The system time was cut by a factor of 3, but the elapsed time doubled.

Putting in shorter naps at 9600 baud brought the elapsed time down, while
increasing the system load moderately.  Essentially, the system time
remained constant when any sleeping was done.  The difference in
percentage of the system used shows that, in effect, the same work
was spread out over different lengths of time.  This results in a tradeoff
that can only be evaluated by each system in terms of their priorities.

An added complication is that most V7 and 4BSD systems do not have
a way to sleep for less than a second.  4.2BSD has the select system
call, or you may have installed a nap system call or the Cornell fast
timer driver.  Otherwise, your only choices are either sleep(1) or
nothing.  The napms call below calls a routine in the new curses, to
sleep for around 1 clock tick (60 ms).

If your top priority is to keep system response good, it is recommended
that you do the sleep(1) no matter what the baud rate is.  If your top
priority is to make 9600 baud transfers go as quickly as possible, you
should do the sleep for 1200 baud or less, and otherwise do nothing.
If you want a well balanced compromise and have a high resolution sleep
or nap or select available, the changes shown here are appropriate.

This change is trivial except for the change to conn.c to make the
baud rate available to the packet driver.  The code dealing with the
speed is different in different versions of UUCP.  If you have trouble
with conn.c, search for the string "speed" and look for a conveniently
available integer version of the speed.  The variable linebaudrate is
a global integer, exported to pk1.c for purposes of this test.  The
changes shown here are for the 4.1BSD version of UUCP.

*** conn.c	Wed Jun  4 01:47:12 1980
--- conn.c.new	Sat Apr  2 18:13:25 1983
***************
*** 85,90
  	char *D_calldev;
  	int D_speed;
  	} Devs [MAXDEV];
  
  char Devbuff[MAXDCH];
  

--- 85,91 -----
  	char *D_calldev;
  	int D_speed;
  	} Devs [MAXDEV];
+ int linebaudrate;
  
  char Devbuff[MAXDCH];
  
***************
*** 344,349
  	alarm(0);
  	fflush(stdout);
  	fixline(dcf, pd->D_speed);
  	DEBUG(4, "Forked %d ", pid);
  	DEBUG(4, "Wait got %d ", nw);
  	DEBUG(4, "Status %o\n", lt);

--- 345,351 -----
  	alarm(0);
  	fflush(stdout);
  	fixline(dcf, pd->D_speed);
+ 	linebaudrate = pd->D_speed;
  	DEBUG(4, "Forked %d ", pid);
  	DEBUG(4, "Wait got %d ", nw);
  	DEBUG(4, "Status %o\n", lt);
*** pk1.c	Mon May 28 00:44:06 1979
--- pk1.c.new	Sat Apr  2 18:16:02 1983
[This is routine pkcget, near the end of pk1.c.]
***************
*** 335,340
  char *b;
  {
  	int nchars, ret;
  
  	if (setjmp(Getjbuf)) {
  		Ntimeout++;

--- 335,341 -----
  char *b;
  {
  	int nchars, ret;
+ 	extern int linebaudrate;
  
  	if (setjmp(Getjbuf)) {
  		Ntimeout++;
***************
*** 343,349
  	}
  	signal(SIGALRM, cgalarm);
  
! 	for (nchars = 0; nchars < n; nchars += ret) {
  		alarm(PKTIME);
  		ret = read(fn, b, n - nchars);
  		if (ret == 0) {

--- 344,350 -----
  	}
  	signal(SIGALRM, cgalarm);
  
! 	for (nchars = 0; nchars < n; ) {
  		alarm(PKTIME);
  		ret = read(fn, b, n - nchars);
  		if (ret == 0) {
***************
*** 352,357
  		}
  		PKASSERT(ret > 0, "PKCGET READ %d", ret);
  		b += ret;
  	}
  	alarm(0);
  	return(0);

--- 353,364 -----
  		}
  		PKASSERT(ret > 0, "PKCGET READ %d", ret);
  		b += ret;
+ 		nchars += ret;
+ 		if (nchars < n)
+ 			if (linebaudrate > 0 && linebaudrate < 4800)
+ 				sleep(1);
+ 			else
+ 				napms(60);
  	}
  	alarm(0);
  	return(0);