/share/doc/papers/sysperf/a1.t
https://bitbucket.org/freebsd/freebsd-head/ · Raku · 668 lines · 668 code · 0 blank · 0 comment · 8 complexity · b9c5284d43cceac389885465f15b7362 MD5 · raw file
- .\" Copyright (c) 1985 The Regents of the University of California.
- .\" All rights reserved.
- .\"
- .\" Redistribution and use in source and binary forms, with or without
- .\" modification, are permitted provided that the following conditions
- .\" are met:
- .\" 1. Redistributions of source code must retain the above copyright
- .\" notice, this list of conditions and the following disclaimer.
- .\" 2. Redistributions in binary form must reproduce the above copyright
- .\" notice, this list of conditions and the following disclaimer in the
- .\" documentation and/or other materials provided with the distribution.
- .\" 3. All advertising materials mentioning features or use of this software
- .\" must display the following acknowledgement:
- .\" This product includes software developed by the University of
- .\" California, Berkeley and its contributors.
- .\" 4. Neither the name of the University nor the names of its contributors
- .\" may be used to endorse or promote products derived from this software
- .\" without specific prior written permission.
- .\"
- .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- .\" SUCH DAMAGE.
- .\"
- .\" @(#)a1.t 5.1 (Berkeley) 4/17/91
- .\"
- .ds RH Appendix A \- Benchmark sources
- .nr H2 1
- .sp 2
- .de vS
- .nf
- ..
- .de vE
- .fi
- ..
- .bp
- .SH
- \s+2Appendix A \- Benchmark sources\s-2
- .LP
- The programs shown here run under 4.2 with only routines
- from the standard libraries. When run under 4.1 they were augmented
- with a \fIgetpagesize\fP routine and a copy of the \fIrandom\fP
- function from the C library. The \fIvforks\fP and \fIvexecs\fP
- programs are constructed from the \fIforks\fP and \fIexecs\fP programs,
- respectively, by substituting calls to \fIfork\fP with calls to
- \fIvfork\fP.
- .SH
- syscall
- .LP
- .vS
- /*
- * System call overhead benchmark.
- */
- main(argc, argv)
- char *argv[];
- {
- register int ncalls;
- if (argc < 2) {
- printf("usage: %s #syscalls\n", argv[0]);
- exit(1);
- }
- ncalls = atoi(argv[1]);
- while (ncalls-- > 0)
- (void) getpid();
- }
- .vE
- .SH
- csw
- .LP
- .vS
- /*
- * Context switching benchmark.
- *
- * Force system to context switch 2*nsigs
- * times by forking and exchanging signals.
- * To calculate system overhead for a context
- * switch, the signocsw program must be run
- * with nsigs. Overhead is then estimated by
- * t1 = time csw <n>
- * t2 = time signocsw <n>
- * overhead = t1 - 2 * t2;
- */
- #include <signal.h>
- int sigsub();
- int otherpid;
- int nsigs;
- main(argc, argv)
- char *argv[];
- {
- int pid;
- if (argc < 2) {
- printf("usage: %s nsignals\n", argv[0]);
- exit(1);
- }
- nsigs = atoi(argv[1]);
- signal(SIGALRM, sigsub);
- otherpid = getpid();
- pid = fork();
- if (pid != 0) {
- otherpid = pid;
- kill(otherpid, SIGALRM);
- }
- for (;;)
- sigpause(0);
- }
- sigsub()
- {
- signal(SIGALRM, sigsub);
- kill(otherpid, SIGALRM);
- if (--nsigs <= 0)
- exit(0);
- }
- .vE
- .SH
- signocsw
- .LP
- .vS
- /*
- * Signal without context switch benchmark.
- */
- #include <signal.h>
- int pid;
- int nsigs;
- int sigsub();
- main(argc, argv)
- char *argv[];
- {
- register int i;
- if (argc < 2) {
- printf("usage: %s nsignals\n", argv[0]);
- exit(1);
- }
- nsigs = atoi(argv[1]);
- signal(SIGALRM, sigsub);
- pid = getpid();
- for (i = 0; i < nsigs; i++)
- kill(pid, SIGALRM);
- }
- sigsub()
- {
- signal(SIGALRM, sigsub);
- }
- .vE
- .SH
- pipeself
- .LP
- .vS
- /*
- * IPC benchmark,
- * write to self using pipes.
- */
- main(argc, argv)
- char *argv[];
- {
- char buf[512];
- int fd[2], msgsize;
- register int i, iter;
- if (argc < 3) {
- printf("usage: %s iterations message-size\n", argv[0]);
- exit(1);
- }
- argc--, argv++;
- iter = atoi(*argv);
- argc--, argv++;
- msgsize = atoi(*argv);
- if (msgsize > sizeof (buf) || msgsize <= 0) {
- printf("%s: Bad message size.\n", *argv);
- exit(2);
- }
- if (pipe(fd) < 0) {
- perror("pipe");
- exit(3);
- }
- for (i = 0; i < iter; i++) {
- write(fd[1], buf, msgsize);
- read(fd[0], buf, msgsize);
- }
- }
- .vE
- .SH
- pipediscard
- .LP
- .vS
- /*
- * IPC benchmarkl,
- * write and discard using pipes.
- */
- main(argc, argv)
- char *argv[];
- {
- char buf[512];
- int fd[2], msgsize;
- register int i, iter;
- if (argc < 3) {
- printf("usage: %s iterations message-size\n", argv[0]);
- exit(1);
- }
- argc--, argv++;
- iter = atoi(*argv);
- argc--, argv++;
- msgsize = atoi(*argv);
- if (msgsize > sizeof (buf) || msgsize <= 0) {
- printf("%s: Bad message size.\n", *argv);
- exit(2);
- }
- if (pipe(fd) < 0) {
- perror("pipe");
- exit(3);
- }
- if (fork() == 0)
- for (i = 0; i < iter; i++)
- read(fd[0], buf, msgsize);
- else
- for (i = 0; i < iter; i++)
- write(fd[1], buf, msgsize);
- }
- .vE
- .SH
- pipeback
- .LP
- .vS
- /*
- * IPC benchmark,
- * read and reply using pipes.
- *
- * Process forks and exchanges messages
- * over a pipe in a request-response fashion.
- */
- main(argc, argv)
- char *argv[];
- {
- char buf[512];
- int fd[2], fd2[2], msgsize;
- register int i, iter;
- if (argc < 3) {
- printf("usage: %s iterations message-size\n", argv[0]);
- exit(1);
- }
- argc--, argv++;
- iter = atoi(*argv);
- argc--, argv++;
- msgsize = atoi(*argv);
- if (msgsize > sizeof (buf) || msgsize <= 0) {
- printf("%s: Bad message size.\n", *argv);
- exit(2);
- }
- if (pipe(fd) < 0) {
- perror("pipe");
- exit(3);
- }
- if (pipe(fd2) < 0) {
- perror("pipe");
- exit(3);
- }
- if (fork() == 0)
- for (i = 0; i < iter; i++) {
- read(fd[0], buf, msgsize);
- write(fd2[1], buf, msgsize);
- }
- else
- for (i = 0; i < iter; i++) {
- write(fd[1], buf, msgsize);
- read(fd2[0], buf, msgsize);
- }
- }
- .vE
- .SH
- forks
- .LP
- .vS
- /*
- * Benchmark program to calculate fork+wait
- * overhead (approximately). Process
- * forks and exits while parent waits.
- * The time to run this program is used
- * in calculating exec overhead.
- */
- main(argc, argv)
- char *argv[];
- {
- register int nforks, i;
- char *cp;
- int pid, child, status, brksize;
- if (argc < 2) {
- printf("usage: %s number-of-forks sbrk-size\n", argv[0]);
- exit(1);
- }
- nforks = atoi(argv[1]);
- if (nforks < 0) {
- printf("%s: bad number of forks\n", argv[1]);
- exit(2);
- }
- brksize = atoi(argv[2]);
- if (brksize < 0) {
- printf("%s: bad size to sbrk\n", argv[2]);
- exit(3);
- }
- cp = (char *)sbrk(brksize);
- if ((int)cp == -1) {
- perror("sbrk");
- exit(4);
- }
- for (i = 0; i < brksize; i += 1024)
- cp[i] = i;
- while (nforks-- > 0) {
- child = fork();
- if (child == -1) {
- perror("fork");
- exit(-1);
- }
- if (child == 0)
- _exit(-1);
- while ((pid = wait(&status)) != -1 && pid != child)
- ;
- }
- exit(0);
- }
- .vE
- .SH
- execs
- .LP
- .vS
- /*
- * Benchmark program to calculate exec
- * overhead (approximately). Process
- * forks and execs "null" test program.
- * The time to run the fork program should
- * then be deducted from this one to
- * estimate the overhead for the exec.
- */
- main(argc, argv)
- char *argv[];
- {
- register int nexecs, i;
- char *cp, *sbrk();
- int pid, child, status, brksize;
- if (argc < 3) {
- printf("usage: %s number-of-execs sbrk-size job-name\n",
- argv[0]);
- exit(1);
- }
- nexecs = atoi(argv[1]);
- if (nexecs < 0) {
- printf("%s: bad number of execs\n", argv[1]);
- exit(2);
- }
- brksize = atoi(argv[2]);
- if (brksize < 0) {
- printf("%s: bad size to sbrk\n", argv[2]);
- exit(3);
- }
- cp = sbrk(brksize);
- if ((int)cp == -1) {
- perror("sbrk");
- exit(4);
- }
- for (i = 0; i < brksize; i += 1024)
- cp[i] = i;
- while (nexecs-- > 0) {
- child = fork();
- if (child == -1) {
- perror("fork");
- exit(-1);
- }
- if (child == 0) {
- execv(argv[3], argv);
- perror("execv");
- _exit(-1);
- }
- while ((pid = wait(&status)) != -1 && pid != child)
- ;
- }
- exit(0);
- }
- .vE
- .SH
- nulljob
- .LP
- .vS
- /*
- * Benchmark "null job" program.
- */
- main(argc, argv)
- char *argv[];
- {
- exit(0);
- }
- .vE
- .SH
- bigjob
- .LP
- .vS
- /*
- * Benchmark "null big job" program.
- */
- /* 250 here is intended to approximate vi's text+data size */
- char space[1024 * 250] = "force into data segment";
- main(argc, argv)
- char *argv[];
- {
- exit(0);
- }
- .vE
- .bp
- .SH
- seqpage
- .LP
- .vS
- /*
- * Sequential page access benchmark.
- */
- #include <sys/vadvise.h>
- char *valloc();
- main(argc, argv)
- char *argv[];
- {
- register i, niter;
- register char *pf, *lastpage;
- int npages = 4096, pagesize, vflag = 0;
- char *pages, *name;
- name = argv[0];
- argc--, argv++;
- again:
- if (argc < 1) {
- usage:
- printf("usage: %s [ -v ] [ -p #pages ] niter\n", name);
- exit(1);
- }
- if (strcmp(*argv, "-p") == 0) {
- argc--, argv++;
- if (argc < 1)
- goto usage;
- npages = atoi(*argv);
- if (npages <= 0) {
- printf("%s: Bad page count.\n", *argv);
- exit(2);
- }
- argc--, argv++;
- goto again;
- }
- if (strcmp(*argv, "-v") == 0) {
- argc--, argv++;
- vflag++;
- goto again;
- }
- niter = atoi(*argv);
- pagesize = getpagesize();
- pages = valloc(npages * pagesize);
- if (pages == (char *)0) {
- printf("Can't allocate %d pages (%2.1f megabytes).\n",
- npages, (npages * pagesize) / (1024. * 1024.));
- exit(3);
- }
- lastpage = pages + (npages * pagesize);
- if (vflag)
- vadvise(VA_SEQL);
- for (i = 0; i < niter; i++)
- for (pf = pages; pf < lastpage; pf += pagesize)
- *pf = 1;
- }
- .vE
- .SH
- randpage
- .LP
- .vS
- /*
- * Random page access benchmark.
- */
- #include <sys/vadvise.h>
- char *valloc();
- int rand();
- main(argc, argv)
- char *argv[];
- {
- register int npages = 4096, pagesize, pn, i, niter;
- int vflag = 0, debug = 0;
- char *pages, *name;
- name = argv[0];
- argc--, argv++;
- again:
- if (argc < 1) {
- usage:
- printf("usage: %s [ -d ] [ -v ] [ -p #pages ] niter\n", name);
- exit(1);
- }
- if (strcmp(*argv, "-p") == 0) {
- argc--, argv++;
- if (argc < 1)
- goto usage;
- npages = atoi(*argv);
- if (npages <= 0) {
- printf("%s: Bad page count.\n", *argv);
- exit(2);
- }
- argc--, argv++;
- goto again;
- }
- if (strcmp(*argv, "-v") == 0) {
- argc--, argv++;
- vflag++;
- goto again;
- }
- if (strcmp(*argv, "-d") == 0) {
- argc--, argv++;
- debug++;
- goto again;
- }
- niter = atoi(*argv);
- pagesize = getpagesize();
- pages = valloc(npages * pagesize);
- if (pages == (char *)0) {
- printf("Can't allocate %d pages (%2.1f megabytes).\n",
- npages, (npages * pagesize) / (1024. * 1024.));
- exit(3);
- }
- if (vflag)
- vadvise(VA_ANOM);
- for (i = 0; i < niter; i++) {
- pn = random() % npages;
- if (debug)
- printf("touch page %d\n", pn);
- pages[pagesize * pn] = 1;
- }
- }
- .vE
- .SH
- gausspage
- .LP
- .vS
- /*
- * Random page access with
- * a gaussian distribution.
- *
- * Allocate a large (zero fill on demand) address
- * space and fault the pages in a random gaussian
- * order.
- */
- float sqrt(), log(), rnd(), cos(), gauss();
- char *valloc();
- int rand();
- main(argc, argv)
- char *argv[];
- {
- register int pn, i, niter, delta;
- register char *pages;
- float sd = 10.0;
- int npages = 4096, pagesize, debug = 0;
- char *name;
- name = argv[0];
- argc--, argv++;
- again:
- if (argc < 1) {
- usage:
- printf(
- "usage: %s [ -d ] [ -p #pages ] [ -s standard-deviation ] iterations\n", name);
- exit(1);
- }
- if (strcmp(*argv, "-s") == 0) {
- argc--, argv++;
- if (argc < 1)
- goto usage;
- sscanf(*argv, "%f", &sd);
- if (sd <= 0) {
- printf("%s: Bad standard deviation.\n", *argv);
- exit(2);
- }
- argc--, argv++;
- goto again;
- }
- if (strcmp(*argv, "-p") == 0) {
- argc--, argv++;
- if (argc < 1)
- goto usage;
- npages = atoi(*argv);
- if (npages <= 0) {
- printf("%s: Bad page count.\n", *argv);
- exit(2);
- }
- argc--, argv++;
- goto again;
- }
- if (strcmp(*argv, "-d") == 0) {
- argc--, argv++;
- debug++;
- goto again;
- }
- niter = atoi(*argv);
- pagesize = getpagesize();
- pages = valloc(npages*pagesize);
- if (pages == (char *)0) {
- printf("Can't allocate %d pages (%2.1f megabytes).\n",
- npages, (npages*pagesize) / (1024. * 1024.));
- exit(3);
- }
- pn = 0;
- for (i = 0; i < niter; i++) {
- delta = gauss(sd, 0.0);
- while (pn + delta < 0 || pn + delta > npages)
- delta = gauss(sd, 0.0);
- pn += delta;
- if (debug)
- printf("touch page %d\n", pn);
- else
- pages[pn * pagesize] = 1;
- }
- }
- float
- gauss(sd, mean)
- float sd, mean;
- {
- register float qa, qb;
- qa = sqrt(log(rnd()) * -2.0);
- qb = 3.14159 * rnd();
- return (qa * cos(qb) * sd + mean);
- }
- float
- rnd()
- {
- static int seed = 1;
- static int biggest = 0x7fffffff;
- return ((float)rand(seed) / (float)biggest);
- }
- .vE