|
|
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);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.