Sync usage with man page.
[netbsd-mini2440.git] / share / doc / papers / sysperf / a1.t
blob3feed4b3b743d961b5a91046ba21af8863d32c8b
1 .\"     $NetBSD: a1.t,v 1.2 1998/01/09 06:54:35 perry Exp $
2 .\"
3 .\" Copyright (c) 1985 The Regents of the University of California.
4 .\" All rights reserved.
5 .\"
6 .\" Redistribution and use in source and binary forms, with or without
7 .\" modification, are permitted provided that the following conditions
8 .\" are met:
9 .\" 1. Redistributions of source code must retain the above copyright
10 .\"    notice, this list of conditions and the following disclaimer.
11 .\" 2. Redistributions in binary form must reproduce the above copyright
12 .\"    notice, this list of conditions and the following disclaimer in the
13 .\"    documentation and/or other materials provided with the distribution.
14 .\" 3. Neither the name of the University nor the names of its contributors
15 .\"    may be used to endorse or promote products derived from this software
16 .\"    without specific prior written permission.
17 .\"
18 .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 .\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 .\" SUCH DAMAGE.
29 .\"
30 .\"     @(#)a1.t        5.1 (Berkeley) 4/17/91
31 .\"
32 .ds RH Appendix A \- Benchmark sources
33 .nr H2 1
34 .sp 2
35 .de vS
36 .nf
38 .de vE
39 .fi
41 .bp
42 .SH
43 \s+2Appendix A \- Benchmark sources\s-2
44 .LP
45 The programs shown here run under 4.2 with only routines
46 from the standard libraries.  When run under 4.1 they were augmented
47 with a \fIgetpagesize\fP routine and a copy of the \fIrandom\fP
48 function from the C library.  The \fIvforks\fP and \fIvexecs\fP
49 programs are constructed from the \fIforks\fP and \fIexecs\fP programs,
50 respectively, by substituting calls to \fIfork\fP with calls to
51 \fIvfork\fP.
52 .SH
53 syscall
54 .LP
55 .vS
57  * System call overhead benchmark.
58  */
59 main(argc, argv)
60         char *argv[];
62         register int ncalls;
64         if (argc < 2) {
65                 printf("usage: %s #syscalls\n", argv[0]);
66                 exit(1);
67         }
68         ncalls = atoi(argv[1]);
69         while (ncalls-- > 0)
70                 (void) getpid();
72 .vE
73 .SH
74 csw
75 .LP
76 .vS
78  * Context switching benchmark.
79  *
80  * Force system to context switch 2*nsigs
81  * times by forking and exchanging signals.
82  * To calculate system overhead for a context
83  * switch, the signocsw program must be run
84  * with nsigs.  Overhead is then estimated by
85  *      t1 = time csw <n>
86  *      t2 = time signocsw <n>
87  *      overhead = t1 - 2 * t2;
88  */
89 #include <signal.h>
91 int     sigsub();
92 int     otherpid;
93 int     nsigs;
95 main(argc, argv)
96         char *argv[];
98         int pid;
100         if (argc < 2) {
101                 printf("usage: %s nsignals\n", argv[0]);
102                 exit(1);
103         }
104         nsigs = atoi(argv[1]);
105         signal(SIGALRM, sigsub);
106         otherpid = getpid();
107         pid = fork();
108         if (pid != 0) {
109                 otherpid = pid;
110                 kill(otherpid, SIGALRM);
111         }
112         for (;;)
113                 sigpause(0);
116 sigsub()
119         signal(SIGALRM, sigsub);
120         kill(otherpid, SIGALRM);
121         if (--nsigs <= 0)
122                 exit(0);
126 signocsw
130  * Signal without context switch benchmark.
131  */
132 #include <signal.h>
134 int     pid;
135 int     nsigs;
136 int     sigsub();
138 main(argc, argv)
139         char *argv[];
141         register int i;
143         if (argc < 2) {
144                 printf("usage: %s nsignals\n", argv[0]);
145                 exit(1);
146         }
147         nsigs = atoi(argv[1]);
148         signal(SIGALRM, sigsub);
149         pid = getpid();
150         for (i = 0; i < nsigs; i++)
151                 kill(pid, SIGALRM);
154 sigsub()
157         signal(SIGALRM, sigsub);
161 pipeself
165  * IPC benchmark,
166  * write to self using pipes.
167  */
169 main(argc, argv)
170         char *argv[];
172         char buf[512];
173         int fd[2], msgsize;
174         register int i, iter;
176         if (argc < 3) {
177                 printf("usage: %s iterations message-size\n", argv[0]);
178                 exit(1);
179         }
180         argc--, argv++;
181         iter = atoi(*argv);
182         argc--, argv++;
183         msgsize = atoi(*argv);
184         if (msgsize > sizeof (buf) || msgsize <= 0) {
185                 printf("%s: Bad message size.\n", *argv);
186                 exit(2);
187         }
188         if (pipe(fd) < 0) {
189                 perror("pipe");
190                 exit(3);
191         }
192         for (i = 0; i < iter; i++) {
193                 write(fd[1], buf, msgsize);
194                 read(fd[0], buf, msgsize);
195         }
199 pipediscard
203  * IPC benchmarkl,
204  * write and discard using pipes.
205  */
207 main(argc, argv)
208         char *argv[];
210         char buf[512];
211         int fd[2], msgsize;
212         register int i, iter;
214         if (argc < 3) {
215                 printf("usage: %s iterations message-size\n", argv[0]);
216                 exit(1);
217         }
218         argc--, argv++;
219         iter = atoi(*argv);
220         argc--, argv++;
221         msgsize = atoi(*argv);
222         if (msgsize > sizeof (buf) || msgsize <= 0) {
223                 printf("%s: Bad message size.\n", *argv);
224                 exit(2);
225         }
226         if (pipe(fd) < 0) {
227                 perror("pipe");
228                 exit(3);
229         }
230         if (fork() == 0)
231                 for (i = 0; i < iter; i++)
232                         read(fd[0], buf, msgsize);
233         else
234                 for (i = 0; i < iter; i++)
235                         write(fd[1], buf, msgsize);
239 pipeback
243  * IPC benchmark,
244  * read and reply using pipes.
246  * Process forks and exchanges messages
247  * over a pipe in a request-response fashion.
248  */
250 main(argc, argv)
251         char *argv[];
253         char buf[512];
254         int fd[2], fd2[2], msgsize;
255         register int i, iter;
257         if (argc < 3) {
258                 printf("usage: %s iterations message-size\n", argv[0]);
259                 exit(1);
260         }
261         argc--, argv++;
262         iter = atoi(*argv);
263         argc--, argv++;
264         msgsize = atoi(*argv);
265         if (msgsize > sizeof (buf) || msgsize <= 0) {
266                 printf("%s: Bad message size.\n", *argv);
267                 exit(2);
268         }
269         if (pipe(fd) < 0) {
270                 perror("pipe");
271                 exit(3);
272         }
273         if (pipe(fd2) < 0) {
274                 perror("pipe");
275                 exit(3);
276         }
277         if (fork() == 0)
278                 for (i = 0; i < iter; i++) {
279                         read(fd[0], buf, msgsize);
280                         write(fd2[1], buf, msgsize);
281                 }
282         else
283                 for (i = 0; i < iter; i++) {
284                         write(fd[1], buf, msgsize);
285                         read(fd2[0], buf, msgsize);
286                 }
290 forks
294  * Benchmark program to calculate fork+wait
295  * overhead (approximately).  Process
296  * forks and exits while parent waits.
297  * The time to run this program is used
298  * in calculating exec overhead.
299  */
301 main(argc, argv)
302         char *argv[];
304         register int nforks, i;
305         char *cp;
306         int pid, child, status, brksize;
308         if (argc < 2) {
309                 printf("usage: %s number-of-forks sbrk-size\n", argv[0]);
310                 exit(1);
311         }
312         nforks = atoi(argv[1]);
313         if (nforks < 0) {
314                 printf("%s: bad number of forks\n", argv[1]);
315                 exit(2);
316         }
317         brksize = atoi(argv[2]);
318         if (brksize < 0) {
319                 printf("%s: bad size to sbrk\n", argv[2]);
320                 exit(3);
321         }
322         cp = (char *)sbrk(brksize);
323         if ((int)cp == -1) {
324                 perror("sbrk");
325                 exit(4);
326         }
327         for (i = 0; i < brksize; i += 1024)
328                 cp[i] = i;
329         while (nforks-- > 0) {
330                 child = fork();
331                 if (child == -1) {
332                         perror("fork");
333                         exit(-1);
334                 }
335                 if (child == 0)
336                         _exit(-1);
337                 while ((pid = wait(&status)) != -1 && pid != child)
338                         ;
339         }
340         exit(0);
344 execs
348  * Benchmark program to calculate exec
349  * overhead (approximately).  Process
350  * forks and execs "null" test program.
351  * The time to run the fork program should
352  * then be deducted from this one to
353  * estimate the overhead for the exec.
354  */
356 main(argc, argv)
357         char *argv[];
359         register int nexecs, i;
360         char *cp, *sbrk();
361         int pid, child, status, brksize;
363         if (argc < 3) {
364                 printf("usage: %s number-of-execs sbrk-size job-name\n",
365                     argv[0]);
366                 exit(1);
367         }
368         nexecs = atoi(argv[1]);
369         if (nexecs < 0) {
370                 printf("%s: bad number of execs\n", argv[1]);
371                 exit(2);
372         }
373         brksize = atoi(argv[2]);
374         if (brksize < 0) {
375                 printf("%s: bad size to sbrk\n", argv[2]);
376                 exit(3);
377         }
378         cp = sbrk(brksize);
379         if ((int)cp == -1) {
380                 perror("sbrk");
381                 exit(4);
382         }
383         for (i = 0; i < brksize; i += 1024)
384                 cp[i] = i;
385         while (nexecs-- > 0) {
386                 child = fork();
387                 if (child == -1) {
388                         perror("fork");
389                         exit(-1);
390                 }
391                 if (child == 0) {
392                         execv(argv[3], argv);
393                         perror("execv");
394                         _exit(-1);
395                 }
396                 while ((pid = wait(&status)) != -1 && pid != child)
397                         ;
398         }
399         exit(0);
403 nulljob
407  * Benchmark "null job" program.
408  */
410 main(argc, argv)
411         char *argv[];
414         exit(0);
418 bigjob
422  * Benchmark "null big job" program.
423  */
424 /* 250 here is intended to approximate vi's text+data size */
425 char    space[1024 * 250] = "force into data segment";
427 main(argc, argv)
428         char *argv[];
431         exit(0);
436 seqpage
440  * Sequential page access benchmark.
441  */
442 #include <sys/vadvise.h>
444 char    *valloc();
446 main(argc, argv)
447         char *argv[];
449         register i, niter;
450         register char *pf, *lastpage;
451         int npages = 4096, pagesize, vflag = 0;
452         char *pages, *name;
454         name = argv[0];
455         argc--, argv++;
456 again:
457         if (argc < 1) {
458 usage:
459                 printf("usage: %s [ -v ] [ -p #pages ] niter\n", name);
460                 exit(1);
461         }
462         if (strcmp(*argv, "-p") == 0) {
463                 argc--, argv++;
464                 if (argc < 1)
465                         goto usage;
466                 npages = atoi(*argv);
467                 if (npages <= 0) {
468                         printf("%s: Bad page count.\n", *argv);
469                         exit(2);
470                 }
471                 argc--, argv++;
472                 goto again;
473         }
474         if (strcmp(*argv, "-v") == 0) {
475                 argc--, argv++;
476                 vflag++;
477                 goto again;
478         }
479         niter = atoi(*argv);
480         pagesize = getpagesize();
481         pages = valloc(npages * pagesize);
482         if (pages == (char *)0) {
483                 printf("Can't allocate %d pages (%2.1f megabytes).\n",
484                     npages, (npages * pagesize) / (1024. * 1024.));
485                 exit(3);
486         }
487         lastpage = pages + (npages * pagesize);
488         if (vflag)
489                 vadvise(VA_SEQL);
490         for (i = 0; i < niter; i++)
491                 for (pf = pages; pf < lastpage; pf += pagesize)
492                         *pf = 1;
496 randpage
500  * Random page access benchmark.
501  */
502 #include <sys/vadvise.h>
504 char    *valloc();
505 int     rand();
507 main(argc, argv)
508         char *argv[];
510         register int npages = 4096, pagesize, pn, i, niter;
511         int vflag = 0, debug = 0;
512         char *pages, *name;
514         name = argv[0];
515         argc--, argv++;
516 again:
517         if (argc < 1) {
518 usage:
519                 printf("usage: %s [ -d ] [ -v ] [ -p #pages ] niter\n", name);
520                 exit(1);
521         }
522         if (strcmp(*argv, "-p") == 0) {
523                 argc--, argv++;
524                 if (argc < 1)
525                         goto usage;
526                 npages = atoi(*argv);
527                 if (npages <= 0) {
528                         printf("%s: Bad page count.\n", *argv);
529                         exit(2);
530                 }
531                 argc--, argv++;
532                 goto again;
533         }
534         if (strcmp(*argv, "-v") == 0) {
535                 argc--, argv++;
536                 vflag++;
537                 goto again;
538         }
539         if (strcmp(*argv, "-d") == 0) {
540                 argc--, argv++;
541                 debug++;
542                 goto again;
543         }
544         niter = atoi(*argv);
545         pagesize = getpagesize();
546         pages = valloc(npages * pagesize);
547         if (pages == (char *)0) {
548                 printf("Can't allocate %d pages (%2.1f megabytes).\n",
549                     npages, (npages * pagesize) / (1024. * 1024.));
550                 exit(3);
551         }
552         if (vflag)
553                 vadvise(VA_ANOM);
554         for (i = 0; i < niter; i++) {
555                 pn = random() % npages;
556                 if (debug)
557                         printf("touch page %d\n", pn);
558                 pages[pagesize * pn] = 1;
559         }
563 gausspage
567  * Random page access with
568  * a gaussian distribution.
570  * Allocate a large (zero fill on demand) address
571  * space and fault the pages in a random gaussian
572  * order.
573  */
575 float   sqrt(), log(), rnd(), cos(), gauss();
576 char    *valloc();
577 int     rand();
579 main(argc, argv)
580         char *argv[];
582         register int pn, i, niter, delta;
583         register char *pages;
584         float sd = 10.0;
585         int npages = 4096, pagesize, debug = 0;
586         char *name;
588         name = argv[0];
589         argc--, argv++;
590 again:
591         if (argc < 1) {
592 usage:
593                 printf(
594 "usage: %s [ -d ] [ -p #pages ] [ -s standard-deviation ] iterations\n", name);
595                 exit(1);
596         }
597         if (strcmp(*argv, "-s") == 0) {
598                 argc--, argv++;
599                 if (argc < 1)
600                         goto usage;
601                 sscanf(*argv, "%f", &sd);
602                 if (sd <= 0) {
603                         printf("%s: Bad standard deviation.\n", *argv);
604                         exit(2);
605                 }
606                 argc--, argv++;
607                 goto again;
608         }
609         if (strcmp(*argv, "-p") == 0) {
610                 argc--, argv++;
611                 if (argc < 1)
612                         goto usage;
613                 npages = atoi(*argv);
614                 if (npages <= 0) {
615                         printf("%s: Bad page count.\n", *argv);
616                         exit(2);
617                 }
618                 argc--, argv++;
619                 goto again;
620         }
621         if (strcmp(*argv, "-d") == 0) {
622                 argc--, argv++;
623                 debug++;
624                 goto again;
625         }
626         niter = atoi(*argv);
627         pagesize = getpagesize();
628         pages = valloc(npages*pagesize);
629         if (pages == (char *)0) {
630                 printf("Can't allocate %d pages (%2.1f megabytes).\n",
631                     npages, (npages*pagesize) / (1024. * 1024.));
632                 exit(3);
633         }
634         pn = 0;
635         for (i = 0; i < niter; i++) {
636                 delta = gauss(sd, 0.0);
637                 while (pn + delta < 0 || pn + delta > npages)
638                         delta = gauss(sd, 0.0);
639                 pn += delta;
640                 if (debug)
641                         printf("touch page %d\n", pn);
642                 else
643                         pages[pn * pagesize] = 1;
644         }
647 float
648 gauss(sd, mean)
649         float sd, mean;
651         register float qa, qb;
653         qa = sqrt(log(rnd()) * -2.0);
654         qb = 3.14159 * rnd();
655         return (qa * cos(qb) * sd + mean);
658 float
659 rnd()
661         static int seed = 1;
662         static int biggest = 0x7fffffff;
664         return ((float)rand(seed) / (float)biggest);