home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1846 < prev    next >
Internet Message Format  |  1990-12-28  |  11KB

  1. From: corey@milton.u.washington.edu (Corey Satten)
  2. Newsgroups: alt.sources
  3. Subject: [ultrix...] Performance Tuning a DEC 5000 Ultrix 4.0 Risc Workstation
  4. Message-ID: <1990Sep20.174348.13393@math.lsa.umich.edu>
  5. Date: 20 Sep 90 17:43:48 GMT
  6.  
  7. Archive-name: kmem/20-Sep-90
  8. Original-posting-by: corey@milton.u.washington.edu (Corey Satten)
  9. Original-subject: Performance Tuning a DEC 5000 Ultrix 4.0 Risc Workstation
  10. Reposted-by: emv@math.lsa.umich.edu (Edward Vielmetti)
  11.  
  12. [Reposted from comp.unix.ultrix,comp.sys.dec.
  13. Comments on this service to emv@math.lsa.umich.edu (Edward Vielmetti).]
  14.  
  15.  
  16. : ----- cut here ----- cut here ----- cut here ----- cut here -----
  17. : This is a "shell archive".  Save everything after the cut mark
  18. : in a file called thisstuff, then feed it to sh by typing sh thisstuff.
  19. : SHAR archive format.  Archive created Thu Sep 20 09:13:16 PDT 1990
  20. echo x - READ_ME
  21. echo '-rw-r--r--  2 corey       6125 Sep 20 09:12 READ_ME    (as sent)'
  22. sed 's/^-//' >READ_ME <<'+FUNKY+STUFF+'
  23. -        Performance Tuning a DEC 5000 Ultrix 4.0 Risc Workstation
  24. -
  25. -        Corey Satten, corey@cac.washington.edu
  26. -                 and
  27. -          Laurence Lundblade, lgl@cac.washington.edu
  28. -
  29. -          Networks and Distributed Computing
  30. -               University of Washington
  31. -              Seattle, Washington
  32. -                September 1990
  33. -
  34. -
  35. -
  36. -History:
  37. -
  38. -      Until August 1990, our department was using a rather maximally
  39. -  configured pmax (DEC 3100 running Ultrix 3.1) as a time-sharing host.
  40. -  It had five disks, mostly Maxtor 660 megs.  It served /usr/local/bin
  41. -  via NFS to about a dozen workstations; was the departmental electronic
  42. -  mail machine; host to some campus wide mailing lists; our anonymous FTP
  43. -  server; one of two campus default domain nameservers; and also
  44. -  time-sharing host for about 16 X-terminals plus about a dozen other users
  45. -  connected via telnet.  We were supporting about 150 megs of swap space
  46. -  on some small portion of the 24 megabyte physical memory.  A 'ps aux'
  47. -  listing usually had 250-300 lines in it.
  48. -
  49. -      As you might guess, the machine wasn't always snappy, but it did
  50. -  admirably.  It was clearly disk i/o limited -- mostly, we assumed,
  51. -  because it was usually thrashing.  Still, the load average was usually
  52. -  between 1-2 and it was mostly the spikes which were annoying.
  53. -
  54. -      Mid August we upgraded to a 3max (DEC 5000) running Ultrix 4.0.  We
  55. -  doubled our RAM to 48 megs, increased our MIPS rating by 50-80% and felt
  56. -  that the system was slower than ever.  According to the `ps' program we
  57. -  were still thrashing even though our active virtual memory was less than
  58. -  the physical memory available to support it.  As we looked more closely,
  59. -  we discovered that the system wasn't even paging, it was swapping, and
  60. -  making stupid choices of what to swap, at that!
  61. -
  62. -Analysis:
  63. -
  64. -      Eventually we decided that the constants involved in the 2-handed
  65. -  clock paging algorithm are no longer appropriate.  In particular:
  66. -
  67. -      lotsfree = 128 (512k)
  68. -      desfree  = 64  (256k)
  69. -      minfree  = 24  (96k)
  70. -      maxpgio  = 60  (4k pages per second)
  71. -      slowscan = 94  (computed)
  72. -      fastscan = 47  (computed/2)
  73. -
  74. -      In the old days, programs were small and the extra memory needed
  75. -  to start several could be obtained from a 512k-byte free list.  Today,
  76. -  programs are bloated with X libraries, etc.  Our average process is
  77. -  about 500k.  At the scan rates we were seeing:  100-200 4k pages/second,
  78. -  scanning simply couldn't keep up with the demand.  Our free list hovered
  79. -  right around the minimum threshold which triggered swapping.
  80. -
  81. -      We examined some old source code and discovered what factors can
  82. -  trigger swapping.  Several of these, such as load>2 are compiled into
  83. -  the kernel as constants or are computed into local variables -- these
  84. -  can only be changed by recompiling the kernel -- something we can't do
  85. -  until DEC releases the current source.  Fortunately a significant number
  86. -  of the terms in the equation are stored in global variables which can
  87. -  be fiddled on a running system.  By changing a few values, we believe
  88. -  we have virtually eliminated swapping on our system and raised the
  89. -  interactive performance level substantially.
  90. -  
  91. -      On our system we have made the following changes:
  92. -
  93. -      lotsfree = 1280 (5 meg)
  94. -      desfree  = 256  (1 meg)
  95. -      minfree  = 64   (256k)
  96. -      maxpgio  = 125  (4k pages per second)
  97. -      slowscan = 30
  98. -      fastscan = 10
  99. -
  100. -      In this way, we try to have 5 megs of free list for programs to
  101. -  absorb transient loads, we can replenish the free list 5 times faster
  102. -  than the default, and we've increased the allowable page-in plus page-out
  103. -  rate to 125 (I can easily make our system burst to 150 and sustain 125,
  104. -  so I don't think 125 is indicative that the paging system is in distress.
  105. -  Also, when choosing your own numbers, remember that vmstat displays `pi'
  106. -  and `po' in 1k pages).
  107. -
  108. -      Since DEC has phased-out adb, I wrote a program to allow us to make
  109. -  these changes.  I've called it `kmem' and it works like this:
  110. -
  111. -      prompt% kmem lotsfree desfree        # to read values
  112. -      lotsfree(0x8014ba40)        1280
  113. -      desfree(0x8014ba48)         256
  114. -
  115. -      prompt% kmem -w lotsfree=1281 desfree=257    # to write values
  116. -      lotsfree(0x8014ba40)        1280 -> 1281
  117. -      desfree(0x8014ba48)         256 -> 257
  118. -
  119. -      Once you find values you're happy with, stick it in /etc/rc.local
  120. -  and be happy.  The source to `kmem' is included in this directory.
  121. -
  122. -Final Disclaimers:
  123. -
  124. -      By re-compiling the kernel, we expect we can do still better.  We
  125. -  believe the clock paging algorithm still isn't working very well and
  126. -  even though we see better performance when paging than swapping, we
  127. -  suspect that because the "global page replacement" algorithm is making
  128. -  its decisions on very local (2megabyte spread between hands) page use
  129. -  data we aren't making very good use of physical memory.  To support this
  130. -  claim, we notice that our cpu usually shows substantial idle time even
  131. -  when the load is greater than 1 and the "active real memory" field we
  132. -  print in our "vmstat" listing (from t_arm) usually shows lots of our
  133. -  physical memory is "inactive" when we think it shouldn't be.
  134. -
  135. -      By increasing desfree to 640 (2.5meg) we can partially re-enable
  136. -  swapping of only "deadwood" (jobs sleeping for longer than 20 seconds).
  137. -  We find this helps increase our active real memory and decrease our idle
  138. -  cpu but at an unacceptable degradation in interactive response time.
  139. -
  140. -      Before I finish, I should probably point out that in addition to the
  141. -  load you might expect on our system, we have 3 anomalies:  first, we
  142. -  have about 60-80 processes such as xclock, which wake-up every now and
  143. -  then to check/update something and then sleep for a short while longer.
  144. -  Second, we have an unusually large number of very popular shell scripts
  145. -  which start dozens of little awks, seds, greps, etc.  Third, we have
  146. -  3 swap disks configured and we think we've done a good job of spreading
  147. -  all disk requests across all the drives.
  148. -
  149. ---------
  150. -Corey Satten, corey@cac.washington.edu
  151. -Networks and Distributed Computing
  152. -University of Washington
  153. +FUNKY+STUFF+
  154. chmod u=rw,g=r,o=r READ_ME
  155. ls -l READ_ME
  156. echo x - kmem.c
  157. echo '-rw-r--r--  2 corey       2910 Sep 10 20:20 kmem.c    (as sent)'
  158. sed 's/^-//' >kmem.c <<'+FUNKY+STUFF+'
  159. -/*
  160. - * a tool to use in place of adb (on systems without adb) which lets you
  161. - * peek and poke at the values of kernel variables in /dev/kmem
  162. - *
  163. - * usage:    kmem var1 var2 ... varN
  164. - *  or
  165. - * usage:    kmem -w var1=val1 var2=val2 ... varN=valN
  166. - *
  167. - * Corey Satten, corey@cac.washington.edu, 9/6/90 - Ultrix 4.0 version
  168. - */
  169. -#include<stdio.h>
  170. -#include<nlist.h>
  171. -#include<sys/file.h>
  172. -
  173. -struct nlist *nl;        /* how we find locations of names */
  174. -int *nv;            /* the new values for each name */
  175. -int w_flag = 0;            /* write new values? */
  176. -char *file = "/vmunix";        /* default file to read symbols from */
  177. -int kmem;
  178. -
  179. -main(argc, argv)
  180. -    int argc;
  181. -    char *argv[];
  182. -{
  183. -    int f;            /* walks argv upto index of first non-flag */
  184. -    int i;            /* walks through remaining arguments */
  185. -    int value = 0;
  186. -    int rc = 0;
  187. -
  188. -    /*
  189. -     * flag parsing
  190. -     */
  191. -    for (f=1; f<argc && *(argv[f]) == '-'; ++f) {
  192. -    switch(argv[f][1]) {
  193. -    default:
  194. -        fprintf(stderr, "%s: unknown flag -%c\n", argv[0], argv[f][1]);
  195. -        exit(1);
  196. -    case 'w':
  197. -        w_flag = 1;
  198. -        break;
  199. -    case 'f':
  200. -        file = argv[++f];
  201. -        break;
  202. -    }
  203. -    }
  204. -
  205. -    /*
  206. -     * handle the remaining arguments as either symname or symname=value
  207. -     * depending on whether -w (w_flag) was specified.
  208. -     */
  209. -
  210. -    nl = (struct nlist *) malloc( sizeof(*nl) * (argc-f+1) );
  211. -    nv = (int *) malloc( sizeof(int) * (argc-f+1) );
  212. -    if (!nv || !nl) {perror("malloc"); exit(1);};
  213. -
  214. -    for (i=0; i<argc-f; ++i) {
  215. -    char *name = (char *)malloc(strlen(argv[i+f]+1));
  216. -
  217. -    if (!name) {perror("malloc"); exit(1);};
  218. -    rc = sscanf(argv[i+f], "%[^=]=%d", name, &value);
  219. -    if (rc - w_flag != 1) {
  220. -        fprintf(stderr, "%s: bad argument: %s\n", argv[0], argv[i+f]);
  221. -        exit(1);
  222. -        }
  223. -    nl[i].n_name = name;
  224. -    nv[i] = value;
  225. -    }
  226. -    nl[i].n_name = "";
  227. -
  228. -    /*
  229. -     * now figure out where to read/write in /dev/kmem and do it
  230. -     */
  231. -    
  232. -    nlist(file, nl);
  233. -
  234. -    kmem = open("/dev/kmem", w_flag ? O_RDWR : O_RDONLY);
  235. -    if (kmem < 0) {
  236. -    perror("/dev/kmem open");
  237. -    exit(1);
  238. -    }
  239. -
  240. -    for (i=0; i<argc-f; ++i) {
  241. -    long seekto = (long)nl[i].n_value;
  242. -
  243. -    if (nl[i].n_type == 0) {
  244. -        fprintf(stderr, "%s: symbol `%s' not found in namelist of %s\n",
  245. -        argv[0], nl[i].n_name, file);
  246. -    /*
  247. -     *  We promise to do all writes in command line order, so if one
  248. -     *  is going to fail, we'd best bail out rather than continue.
  249. -     */
  250. -        if (w_flag) exit(2);
  251. -        else    continue;
  252. -        }
  253. -    if ( lseek(kmem, seekto, 0) != seekto ) {
  254. -        perror("/dev/kmem lseek"); exit(2);
  255. -        }
  256. -    if ( read(kmem, &value, sizeof(int)) != sizeof(int) ) {
  257. -        perror("/dev/kmem read"); exit(2);
  258. -        }
  259. -
  260. -    printf("%s(0x%x)\t%d", nl[i].n_name, nl[i].n_value, value);
  261. -
  262. -    if (w_flag) {
  263. -        if ( lseek(kmem, seekto, 0) != seekto ) {
  264. -        perror("/dev/kmem lseek"); exit(2);
  265. -        }
  266. -        value = nv[i];
  267. -        printf(" -> %d", value);
  268. -        if ( write(kmem, &value, sizeof(int)) != sizeof(int) ) {
  269. -        perror("/dev/kmem write"); exit(2);
  270. -        }
  271. -        }
  272. -    putchar('\n');
  273. -    }
  274. -}
  275. +FUNKY+STUFF+
  276. chmod u=rw,g=r,o=r kmem.c
  277. ls -l kmem.c
  278. echo x - Makefile
  279. echo '-rw-r--r--  2 corey         28 Sep 10 17:56 Makefile    (as sent)'
  280. sed 's/^-//' >Makefile <<'+FUNKY+STUFF+'
  281. -kmem:    kmem.o
  282. -    cc -o $@ $@.o
  283. +FUNKY+STUFF+
  284. chmod u=rw,g=r,o=r Makefile
  285. ls -l Makefile
  286. exit 0
  287.