+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);