BSD 4_3_Tahoe development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 13 Apr 1983 04:30:13 +0000 (20:30 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 13 Apr 1983 04:30:13 +0000 (20:30 -0800)
Work on file usr/src/new/news/uucp/cpu.speedup

Synthesized-from: CSRG/cd2/4.3tahoe

usr/src/new/news/uucp/cpu.speedup [new file with mode: 0644]

diff --git a/usr/src/new/news/uucp/cpu.speedup b/usr/src/new/news/uucp/cpu.speedup
new file mode 100644 (file)
index 0000000..d2716f1
--- /dev/null
@@ -0,0 +1,207 @@
+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);