Annotation of 43BSD/contrib/news/uucp/cpu.speedup, revision 1.1

1.1     ! root        1: Under certain circumstances, you may find that when 2 or 3 uucicos
        !             2: are running on your system, they are eating up all the CPU time,
        !             3: and system performance suffers horribly.  If this is your problem,
        !             4: you can do a "vmstat 5" and watch the system calls and context switches
        !             5: counters.  If they are both very high whenever 2 or more uucicos
        !             6: are running (100-200 system calls/second, over 100 context switches),
        !             7: chances are that the problem is as follows:
        !             8: 
        !             9: When another system is sending you a file, your uucico reads characters
        !            10: from the line.  The read returns whatever is there waiting, or if
        !            11: nothing is waiting, waits for one character and returns.  Since uucico
        !            12: usually wants 64 characters at a time, at 1200 baud it's quite common
        !            13: to read these in 1 or 2 character pieces.  Each uucico will read 1 or
        !            14: 2 characters, wake up the user process, go back for more, there won't
        !            15: be any, so it hangs and gives up the CPU.  A very short time later,
        !            16: (often within the same clock tick) there will be a character available,
        !            17: the process will wake up, read one character, and try again.
        !            18: 
        !            19: This modification is very simple.  If the first read returned fewer
        !            20: characters than requested, before doing another read, the process
        !            21: will sleep for one second.  Then, when it wakes up, there will probably
        !            22: be as many characters waiting as it needs.
        !            23: 
        !            24: This modification makes a big difference when you are RECEIVING a file
        !            25: from another system.  It won't make much difference when you are
        !            26: SENDING a file, because the user process doesn't usually have to hang
        !            27: to write to the line, and when it does, the high/low water mark
        !            28: mechanism in the tty driver keeps it from waking up too often.
        !            29: This change is intended for a V7 or 4BSD system.  It may not
        !            30: help much on System V, because uucp uses a USG tty driver feature
        !            31: to make it wake up only every 6 characters.
        !            32: 
        !            33: The amount this fix helps depends a LOT on the baud rate.  Since it
        !            34: is sleeping while it had been reading characters, it is reasonable
        !            35: to expect the file to get transferred more slowly than before.  This
        !            36: might, in turn, lead to increased phone bills.  Some experimentation
        !            37: receiving a file over a hardwired link is detailed here.  The file
        !            38: received is /etc/termcap, which is 66405 bytes long.  The local system
        !            39: is a 4.1BSD VAX 11/750, the remote system is a UNIX 5.0 VAX 11/750.
        !            40: The link is over a develcon dataswitch.  Both systems were almost
        !            41: idle, although when another uucico did start up, it didn't seem to
        !            42: affect the numbers.  The commands
        !            43:        uucp -r othersys!~/termcap ~uucp/termcap
        !            44:        time /usr/lib/uucp/uucico -r1 -sothersys
        !            45: were given.
        !            46: 
        !            47: "type" is the type of uucico run: "old" is without the sleep, "sleep"
        !            48: has a sleep(1) added after every short read, "nap" is the same as
        !            49: sleep except that at 4800 baud and higher the sleep is for less than
        !            50: one second (the parameter is the number of milliseconds).  "user" and
        !            51: "sys" are the user and system CPU times from the time command, in
        !            52: seconds.  "elapsed" is the time, in seconds, to transfer the file,
        !            53: taken from /usr/spool/uucp/SYSLOG.  (Elapsed time does not include time to
        !            54: get the connection going or close it down, just to transfer the file.)
        !            55: "%" is the percentage of the system the uucico command took, from the
        !            56: time command.
        !            57: 
        !            58: type   speed   user    sys     elapsed %
        !            59: 
        !            60: old    1200    35.3    120.8   606     21%
        !            61: sleep  1200    14.2     35.9   609      7%
        !            62: 
        !            63: old    2400    27.4    115.8   305     31%
        !            64: sleep  2400    13.2     35.0   351      9%
        !            65: 
        !            66: old    4800    23.9    116.0   152     57%
        !            67: sleep  4800    14.4     40.3   338     12%
        !            68: 
        !            69: old    9600    14.4     68.1   79      42%
        !            70: nap 60 9600    14.6     52.7   97      39%
        !            71: nap 100        9600    14.9     48.5   113     32%
        !            72: nap 200        9600    15.0     47.1   127     37%
        !            73: sleep  9600    12.0     46.1   279     15%
        !            74: 
        !            75: It is clear that at 2400 baud or less, the load on the system was
        !            76: cut considerably, while the penalty in slower transfer speed is
        !            77: negligible.  At 9600 baud, the sleep version (equivalent to nap 1000)
        !            78: cut the system load by about 1/3, the elapsed time shot way up.
        !            79: (It takes much less than 1 second to accumulate 64 characters at
        !            80: 9600 baud.) At 4800 baud the results are somewhere in between.
        !            81: The system time was cut by a factor of 3, but the elapsed time doubled.
        !            82: 
        !            83: Putting in shorter naps at 9600 baud brought the elapsed time down, while
        !            84: increasing the system load moderately.  Essentially, the system time
        !            85: remained constant when any sleeping was done.  The difference in
        !            86: percentage of the system used shows that, in effect, the same work
        !            87: was spread out over different lengths of time.  This results in a tradeoff
        !            88: that can only be evaluated by each system in terms of their priorities.
        !            89: 
        !            90: An added complication is that most V7 and 4BSD systems do not have
        !            91: a way to sleep for less than a second.  4.2BSD has the select system
        !            92: call, or you may have installed a nap system call or the Cornell fast
        !            93: timer driver.  Otherwise, your only choices are either sleep(1) or
        !            94: nothing.  The napms call below calls a routine in the new curses, to
        !            95: sleep for around 1 clock tick (60 ms).
        !            96: 
        !            97: If your top priority is to keep system response good, it is recommended
        !            98: that you do the sleep(1) no matter what the baud rate is.  If your top
        !            99: priority is to make 9600 baud transfers go as quickly as possible, you
        !           100: should do the sleep for 1200 baud or less, and otherwise do nothing.
        !           101: If you want a well balanced compromise and have a high resolution sleep
        !           102: or nap or select available, the changes shown here are appropriate.
        !           103: 
        !           104: This change is trivial except for the change to conn.c to make the
        !           105: baud rate available to the packet driver.  The code dealing with the
        !           106: speed is different in different versions of UUCP.  If you have trouble
        !           107: with conn.c, search for the string "speed" and look for a conveniently
        !           108: available integer version of the speed.  The variable linebaudrate is
        !           109: a global integer, exported to pk1.c for purposes of this test.  The
        !           110: changes shown here are for the 4.1BSD version of UUCP.
        !           111: 
        !           112: *** conn.c     Wed Jun  4 01:47:12 1980
        !           113: --- conn.c.new Sat Apr  2 18:13:25 1983
        !           114: ***************
        !           115: *** 85,90
        !           116:        char *D_calldev;
        !           117:        int D_speed;
        !           118:        } Devs [MAXDEV];
        !           119:   
        !           120:   char Devbuff[MAXDCH];
        !           121:   
        !           122: 
        !           123: --- 85,91 -----
        !           124:        char *D_calldev;
        !           125:        int D_speed;
        !           126:        } Devs [MAXDEV];
        !           127: + int linebaudrate;
        !           128:   
        !           129:   char Devbuff[MAXDCH];
        !           130:   
        !           131: ***************
        !           132: *** 344,349
        !           133:        alarm(0);
        !           134:        fflush(stdout);
        !           135:        fixline(dcf, pd->D_speed);
        !           136:        DEBUG(4, "Forked %d ", pid);
        !           137:        DEBUG(4, "Wait got %d ", nw);
        !           138:        DEBUG(4, "Status %o\n", lt);
        !           139: 
        !           140: --- 345,351 -----
        !           141:        alarm(0);
        !           142:        fflush(stdout);
        !           143:        fixline(dcf, pd->D_speed);
        !           144: +      linebaudrate = pd->D_speed;
        !           145:        DEBUG(4, "Forked %d ", pid);
        !           146:        DEBUG(4, "Wait got %d ", nw);
        !           147:        DEBUG(4, "Status %o\n", lt);
        !           148: *** pk1.c      Mon May 28 00:44:06 1979
        !           149: --- pk1.c.new  Sat Apr  2 18:16:02 1983
        !           150: [This is routine pkcget, near the end of pk1.c.]
        !           151: ***************
        !           152: *** 335,340
        !           153:   char *b;
        !           154:   {
        !           155:        int nchars, ret;
        !           156:   
        !           157:        if (setjmp(Getjbuf)) {
        !           158:                Ntimeout++;
        !           159: 
        !           160: --- 335,341 -----
        !           161:   char *b;
        !           162:   {
        !           163:        int nchars, ret;
        !           164: +      extern int linebaudrate;
        !           165:   
        !           166:        if (setjmp(Getjbuf)) {
        !           167:                Ntimeout++;
        !           168: ***************
        !           169: *** 343,349
        !           170:        }
        !           171:        signal(SIGALRM, cgalarm);
        !           172:   
        !           173: !      for (nchars = 0; nchars < n; nchars += ret) {
        !           174:                alarm(PKTIME);
        !           175:                ret = read(fn, b, n - nchars);
        !           176:                if (ret == 0) {
        !           177: 
        !           178: --- 344,350 -----
        !           179:        }
        !           180:        signal(SIGALRM, cgalarm);
        !           181:   
        !           182: !      for (nchars = 0; nchars < n; ) {
        !           183:                alarm(PKTIME);
        !           184:                ret = read(fn, b, n - nchars);
        !           185:                if (ret == 0) {
        !           186: ***************
        !           187: *** 352,357
        !           188:                }
        !           189:                PKASSERT(ret > 0, "PKCGET READ %d", ret);
        !           190:                b += ret;
        !           191:        }
        !           192:        alarm(0);
        !           193:        return(0);
        !           194: 
        !           195: --- 353,364 -----
        !           196:                }
        !           197:                PKASSERT(ret > 0, "PKCGET READ %d", ret);
        !           198:                b += ret;
        !           199: +              nchars += ret;
        !           200: +              if (nchars < n)
        !           201: +                      if (linebaudrate > 0 && linebaudrate < 4800)
        !           202: +                              sleep(1);
        !           203: +                      else
        !           204: +                              napms(60);
        !           205:        }
        !           206:        alarm(0);
        !           207:        return(0);

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.