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