new copyright; att/bsd/shared
[unix-history] / usr / src / share / doc / papers / sysperf / a1.t
CommitLineData
c77af78a
KB
1.\" Copyright (c) 1985 The Regents of the University of California.
2.\" All rights reserved.
4cdc62b8 3.\"
3edcb7c8 4.\" %sccs.include.redist.man%
c77af78a 5.\"
3edcb7c8 6.\" @(#)a1.t 5.1 (Berkeley) %G%
4cdc62b8
KM
7.\"
8.ds RH Appendix A \- Benchmark sources
9.nr H2 1
10.sp 2
11.de vS
12.nf
13..
14.de vE
15.fi
16..
17.bp
18.SH
19\s+2Appendix A \- Benchmark sources\s-2
20.LP
21The programs shown here run under 4.2 with only routines
22from the standard libraries. When run under 4.1 they were augmented
23with a \fIgetpagesize\fP routine and a copy of the \fIrandom\fP
24function from the C library. The \fIvforks\fP and \fIvexecs\fP
25programs are constructed from the \fIforks\fP and \fIexecs\fP programs,
26respectively, by substituting calls to \fIfork\fP with calls to
27\fIvfork\fP.
28.SH
29syscall
30.LP
31.vS
32/*
33 * System call overhead benchmark.
34 */
35main(argc, argv)
36 char *argv[];
37{
38 register int ncalls;
39
40 if (argc < 2) {
41 printf("usage: %s #syscalls\n", argv[0]);
42 exit(1);
43 }
44 ncalls = atoi(argv[1]);
45 while (ncalls-- > 0)
46 (void) getpid();
47}
48.vE
49.SH
50csw
51.LP
52.vS
53/*
54 * Context switching benchmark.
55 *
56 * Force system to context switch 2*nsigs
57 * times by forking and exchanging signals.
58 * To calculate system overhead for a context
59 * switch, the signocsw program must be run
60 * with nsigs. Overhead is then estimated by
61 * t1 = time csw <n>
62 * t2 = time signocsw <n>
63 * overhead = t1 - 2 * t2;
64 */
65#include <signal.h>
66
67int sigsub();
68int otherpid;
69int nsigs;
70
71main(argc, argv)
72 char *argv[];
73{
74 int pid;
75
76 if (argc < 2) {
77 printf("usage: %s nsignals\n", argv[0]);
78 exit(1);
79 }
80 nsigs = atoi(argv[1]);
81 signal(SIGALRM, sigsub);
82 otherpid = getpid();
83 pid = fork();
84 if (pid != 0) {
85 otherpid = pid;
86 kill(otherpid, SIGALRM);
87 }
88 for (;;)
89 sigpause(0);
90}
91
92sigsub()
93{
94
95 signal(SIGALRM, sigsub);
96 kill(otherpid, SIGALRM);
97 if (--nsigs <= 0)
98 exit(0);
99}
100.vE
101.SH
102signocsw
103.LP
104.vS
105/*
106 * Signal without context switch benchmark.
107 */
108#include <signal.h>
109
110int pid;
111int nsigs;
112int sigsub();
113
114main(argc, argv)
115 char *argv[];
116{
117 register int i;
118
119 if (argc < 2) {
120 printf("usage: %s nsignals\n", argv[0]);
121 exit(1);
122 }
123 nsigs = atoi(argv[1]);
124 signal(SIGALRM, sigsub);
125 pid = getpid();
126 for (i = 0; i < nsigs; i++)
127 kill(pid, SIGALRM);
128}
129
130sigsub()
131{
132
133 signal(SIGALRM, sigsub);
134}
135.vE
136.SH
137pipeself
138.LP
139.vS
140/*
141 * IPC benchmark,
142 * write to self using pipes.
143 */
144
145main(argc, argv)
146 char *argv[];
147{
148 char buf[512];
149 int fd[2], msgsize;
150 register int i, iter;
151
152 if (argc < 3) {
153 printf("usage: %s iterations message-size\n", argv[0]);
154 exit(1);
155 }
156 argc--, argv++;
157 iter = atoi(*argv);
158 argc--, argv++;
159 msgsize = atoi(*argv);
160 if (msgsize > sizeof (buf) || msgsize <= 0) {
161 printf("%s: Bad message size.\n", *argv);
162 exit(2);
163 }
164 if (pipe(fd) < 0) {
165 perror("pipe");
166 exit(3);
167 }
168 for (i = 0; i < iter; i++) {
169 write(fd[1], buf, msgsize);
170 read(fd[0], buf, msgsize);
171 }
172}
173.vE
174.SH
175pipediscard
176.LP
177.vS
178/*
179 * IPC benchmarkl,
180 * write and discard using pipes.
181 */
182
183main(argc, argv)
184 char *argv[];
185{
186 char buf[512];
187 int fd[2], msgsize;
188 register int i, iter;
189
190 if (argc < 3) {
191 printf("usage: %s iterations message-size\n", argv[0]);
192 exit(1);
193 }
194 argc--, argv++;
195 iter = atoi(*argv);
196 argc--, argv++;
197 msgsize = atoi(*argv);
198 if (msgsize > sizeof (buf) || msgsize <= 0) {
199 printf("%s: Bad message size.\n", *argv);
200 exit(2);
201 }
202 if (pipe(fd) < 0) {
203 perror("pipe");
204 exit(3);
205 }
206 if (fork() == 0)
207 for (i = 0; i < iter; i++)
208 read(fd[0], buf, msgsize);
209 else
210 for (i = 0; i < iter; i++)
211 write(fd[1], buf, msgsize);
212}
213.vE
214.SH
215pipeback
216.LP
217.vS
218/*
219 * IPC benchmark,
220 * read and reply using pipes.
221 *
222 * Process forks and exchanges messages
223 * over a pipe in a request-response fashion.
224 */
225
226main(argc, argv)
227 char *argv[];
228{
229 char buf[512];
230 int fd[2], fd2[2], msgsize;
231 register int i, iter;
232
233 if (argc < 3) {
234 printf("usage: %s iterations message-size\n", argv[0]);
235 exit(1);
236 }
237 argc--, argv++;
238 iter = atoi(*argv);
239 argc--, argv++;
240 msgsize = atoi(*argv);
241 if (msgsize > sizeof (buf) || msgsize <= 0) {
242 printf("%s: Bad message size.\n", *argv);
243 exit(2);
244 }
245 if (pipe(fd) < 0) {
246 perror("pipe");
247 exit(3);
248 }
249 if (pipe(fd2) < 0) {
250 perror("pipe");
251 exit(3);
252 }
253 if (fork() == 0)
254 for (i = 0; i < iter; i++) {
255 read(fd[0], buf, msgsize);
256 write(fd2[1], buf, msgsize);
257 }
258 else
259 for (i = 0; i < iter; i++) {
260 write(fd[1], buf, msgsize);
261 read(fd2[0], buf, msgsize);
262 }
263}
264.vE
265.SH
266forks
267.LP
268.vS
269/*
270 * Benchmark program to calculate fork+wait
271 * overhead (approximately). Process
272 * forks and exits while parent waits.
273 * The time to run this program is used
274 * in calculating exec overhead.
275 */
276
277main(argc, argv)
278 char *argv[];
279{
280 register int nforks, i;
281 char *cp;
282 int pid, child, status, brksize;
283
284 if (argc < 2) {
285 printf("usage: %s number-of-forks sbrk-size\n", argv[0]);
286 exit(1);
287 }
288 nforks = atoi(argv[1]);
289 if (nforks < 0) {
290 printf("%s: bad number of forks\n", argv[1]);
291 exit(2);
292 }
293 brksize = atoi(argv[2]);
294 if (brksize < 0) {
295 printf("%s: bad size to sbrk\n", argv[2]);
296 exit(3);
297 }
298 cp = (char *)sbrk(brksize);
299 if ((int)cp == -1) {
300 perror("sbrk");
301 exit(4);
302 }
303 for (i = 0; i < brksize; i += 1024)
304 cp[i] = i;
305 while (nforks-- > 0) {
306 child = fork();
307 if (child == -1) {
308 perror("fork");
309 exit(-1);
310 }
311 if (child == 0)
312 _exit(-1);
313 while ((pid = wait(&status)) != -1 && pid != child)
314 ;
315 }
316 exit(0);
317}
318.vE
319.SH
320execs
321.LP
322.vS
323/*
324 * Benchmark program to calculate exec
325 * overhead (approximately). Process
326 * forks and execs "null" test program.
327 * The time to run the fork program should
328 * then be deducted from this one to
329 * estimate the overhead for the exec.
330 */
331
332main(argc, argv)
333 char *argv[];
334{
335 register int nexecs, i;
336 char *cp, *sbrk();
337 int pid, child, status, brksize;
338
339 if (argc < 3) {
340 printf("usage: %s number-of-execs sbrk-size job-name\n",
341 argv[0]);
342 exit(1);
343 }
344 nexecs = atoi(argv[1]);
345 if (nexecs < 0) {
346 printf("%s: bad number of execs\n", argv[1]);
347 exit(2);
348 }
349 brksize = atoi(argv[2]);
350 if (brksize < 0) {
351 printf("%s: bad size to sbrk\n", argv[2]);
352 exit(3);
353 }
354 cp = sbrk(brksize);
355 if ((int)cp == -1) {
356 perror("sbrk");
357 exit(4);
358 }
359 for (i = 0; i < brksize; i += 1024)
360 cp[i] = i;
361 while (nexecs-- > 0) {
362 child = fork();
363 if (child == -1) {
364 perror("fork");
365 exit(-1);
366 }
367 if (child == 0) {
368 execv(argv[3], argv);
369 perror("execv");
370 _exit(-1);
371 }
372 while ((pid = wait(&status)) != -1 && pid != child)
373 ;
374 }
375 exit(0);
376}
377.vE
378.SH
379nulljob
380.LP
381.vS
382/*
383 * Benchmark "null job" program.
384 */
385
386main(argc, argv)
387 char *argv[];
388{
389
390 exit(0);
391}
392.vE
393.SH
394bigjob
395.LP
396.vS
397/*
398 * Benchmark "null big job" program.
399 */
400/* 250 here is intended to approximate vi's text+data size */
401char space[1024 * 250] = "force into data segment";
402
403main(argc, argv)
404 char *argv[];
405{
406
407 exit(0);
408}
409.vE
410.bp
411.SH
412seqpage
413.LP
414.vS
415/*
416 * Sequential page access benchmark.
417 */
418#include <sys/vadvise.h>
419
420char *valloc();
421
422main(argc, argv)
423 char *argv[];
424{
425 register i, niter;
426 register char *pf, *lastpage;
427 int npages = 4096, pagesize, vflag = 0;
428 char *pages, *name;
429
430 name = argv[0];
431 argc--, argv++;
432again:
433 if (argc < 1) {
434usage:
435 printf("usage: %s [ -v ] [ -p #pages ] niter\n", name);
436 exit(1);
437 }
438 if (strcmp(*argv, "-p") == 0) {
439 argc--, argv++;
440 if (argc < 1)
441 goto usage;
442 npages = atoi(*argv);
443 if (npages <= 0) {
444 printf("%s: Bad page count.\n", *argv);
445 exit(2);
446 }
447 argc--, argv++;
448 goto again;
449 }
450 if (strcmp(*argv, "-v") == 0) {
451 argc--, argv++;
452 vflag++;
453 goto again;
454 }
455 niter = atoi(*argv);
456 pagesize = getpagesize();
457 pages = valloc(npages * pagesize);
458 if (pages == (char *)0) {
459 printf("Can't allocate %d pages (%2.1f megabytes).\n",
460 npages, (npages * pagesize) / (1024. * 1024.));
461 exit(3);
462 }
463 lastpage = pages + (npages * pagesize);
464 if (vflag)
465 vadvise(VA_SEQL);
466 for (i = 0; i < niter; i++)
467 for (pf = pages; pf < lastpage; pf += pagesize)
468 *pf = 1;
469}
470.vE
471.SH
472randpage
473.LP
474.vS
475/*
476 * Random page access benchmark.
477 */
478#include <sys/vadvise.h>
479
480char *valloc();
481int rand();
482
483main(argc, argv)
484 char *argv[];
485{
486 register int npages = 4096, pagesize, pn, i, niter;
487 int vflag = 0, debug = 0;
488 char *pages, *name;
489
490 name = argv[0];
491 argc--, argv++;
492again:
493 if (argc < 1) {
494usage:
495 printf("usage: %s [ -d ] [ -v ] [ -p #pages ] niter\n", name);
496 exit(1);
497 }
498 if (strcmp(*argv, "-p") == 0) {
499 argc--, argv++;
500 if (argc < 1)
501 goto usage;
502 npages = atoi(*argv);
503 if (npages <= 0) {
504 printf("%s: Bad page count.\n", *argv);
505 exit(2);
506 }
507 argc--, argv++;
508 goto again;
509 }
510 if (strcmp(*argv, "-v") == 0) {
511 argc--, argv++;
512 vflag++;
513 goto again;
514 }
515 if (strcmp(*argv, "-d") == 0) {
516 argc--, argv++;
517 debug++;
518 goto again;
519 }
520 niter = atoi(*argv);
521 pagesize = getpagesize();
522 pages = valloc(npages * pagesize);
523 if (pages == (char *)0) {
524 printf("Can't allocate %d pages (%2.1f megabytes).\n",
525 npages, (npages * pagesize) / (1024. * 1024.));
526 exit(3);
527 }
528 if (vflag)
529 vadvise(VA_ANOM);
530 for (i = 0; i < niter; i++) {
531 pn = random() % npages;
532 if (debug)
533 printf("touch page %d\n", pn);
534 pages[pagesize * pn] = 1;
535 }
536}
537.vE
538.SH
539gausspage
540.LP
541.vS
542/*
543 * Random page access with
544 * a gaussian distribution.
545 *
546 * Allocate a large (zero fill on demand) address
547 * space and fault the pages in a random gaussian
548 * order.
549 */
550
551float sqrt(), log(), rnd(), cos(), gauss();
552char *valloc();
553int rand();
554
555main(argc, argv)
556 char *argv[];
557{
558 register int pn, i, niter, delta;
559 register char *pages;
560 float sd = 10.0;
561 int npages = 4096, pagesize, debug = 0;
562 char *name;
563
564 name = argv[0];
565 argc--, argv++;
566again:
567 if (argc < 1) {
568usage:
569 printf(
570"usage: %s [ -d ] [ -p #pages ] [ -s standard-deviation ] iterations\n", name);
571 exit(1);
572 }
573 if (strcmp(*argv, "-s") == 0) {
574 argc--, argv++;
575 if (argc < 1)
576 goto usage;
577 sscanf(*argv, "%f", &sd);
578 if (sd <= 0) {
579 printf("%s: Bad standard deviation.\n", *argv);
580 exit(2);
581 }
582 argc--, argv++;
583 goto again;
584 }
585 if (strcmp(*argv, "-p") == 0) {
586 argc--, argv++;
587 if (argc < 1)
588 goto usage;
589 npages = atoi(*argv);
590 if (npages <= 0) {
591 printf("%s: Bad page count.\n", *argv);
592 exit(2);
593 }
594 argc--, argv++;
595 goto again;
596 }
597 if (strcmp(*argv, "-d") == 0) {
598 argc--, argv++;
599 debug++;
600 goto again;
601 }
602 niter = atoi(*argv);
603 pagesize = getpagesize();
604 pages = valloc(npages*pagesize);
605 if (pages == (char *)0) {
606 printf("Can't allocate %d pages (%2.1f megabytes).\n",
607 npages, (npages*pagesize) / (1024. * 1024.));
608 exit(3);
609 }
610 pn = 0;
611 for (i = 0; i < niter; i++) {
612 delta = gauss(sd, 0.0);
613 while (pn + delta < 0 || pn + delta > npages)
614 delta = gauss(sd, 0.0);
615 pn += delta;
616 if (debug)
617 printf("touch page %d\n", pn);
618 else
619 pages[pn * pagesize] = 1;
620 }
621}
622
623float
624gauss(sd, mean)
625 float sd, mean;
626{
627 register float qa, qb;
628
629 qa = sqrt(log(rnd()) * -2.0);
630 qb = 3.14159 * rnd();
631 return (qa * cos(qb) * sd + mean);
632}
633
634float
635rnd()
636{
637 static int seed = 1;
638 static int biggest = 0x7fffffff;
639
640 return ((float)rand(seed) / (float)biggest);
641}
642.vE