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