PageRenderTime 95ms CodeModel.GetById 13ms app.highlight 77ms RepoModel.GetById 1ms app.codeStats 0ms

/share/doc/papers/sysperf/a1.t

https://bitbucket.org/freebsd/freebsd-head/
Unknown | 668 lines | 630 code | 38 blank | 0 comment | 0 complexity | b9c5284d43cceac389885465f15b7362 MD5 | raw file
  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
 47The programs shown here run under 4.2 with only routines
 48from the standard libraries.  When run under 4.1 they were augmented
 49with a \fIgetpagesize\fP routine and a copy of the \fIrandom\fP
 50function from the C library.  The \fIvforks\fP and \fIvexecs\fP
 51programs are constructed from the \fIforks\fP and \fIexecs\fP programs,
 52respectively, by substituting calls to \fIfork\fP with calls to
 53\fIvfork\fP.
 54.SH
 55syscall
 56.LP
 57.vS
 58/*
 59 * System call overhead benchmark.
 60 */
 61main(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
 76csw
 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
 93int	sigsub();
 94int	otherpid;
 95int	nsigs;
 96
 97main(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
118sigsub()
119{
120
121	signal(SIGALRM, sigsub);
122	kill(otherpid, SIGALRM);
123	if (--nsigs <= 0)
124		exit(0);
125}
126.vE
127.SH
128signocsw
129.LP
130.vS
131/*
132 * Signal without context switch benchmark.
133 */
134#include <signal.h>
135
136int	pid;
137int	nsigs;
138int	sigsub();
139
140main(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
156sigsub()
157{
158
159	signal(SIGALRM, sigsub);
160}
161.vE
162.SH
163pipeself
164.LP
165.vS
166/*
167 * IPC benchmark,
168 * write to self using pipes.
169 */
170
171main(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
201pipediscard
202.LP
203.vS
204/*
205 * IPC benchmarkl,
206 * write and discard using pipes.
207 */
208
209main(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
241pipeback
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
252main(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
292forks
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
303main(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
346execs
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
358main(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
405nulljob
406.LP
407.vS
408/*
409 * Benchmark "null job" program.
410 */
411
412main(argc, argv)
413	char *argv[];
414{
415
416	exit(0);
417}
418.vE
419.SH
420bigjob
421.LP
422.vS
423/*
424 * Benchmark "null big job" program.
425 */
426/* 250 here is intended to approximate vi's text+data size */
427char	space[1024 * 250] = "force into data segment";
428
429main(argc, argv)
430	char *argv[];
431{
432
433	exit(0);
434}
435.vE
436.bp
437.SH
438seqpage
439.LP
440.vS
441/*
442 * Sequential page access benchmark.
443 */
444#include <sys/vadvise.h>
445
446char	*valloc();
447
448main(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++;
458again:
459	if (argc < 1) {
460usage:
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
498randpage
499.LP
500.vS
501/*
502 * Random page access benchmark.
503 */
504#include <sys/vadvise.h>
505
506char	*valloc();
507int	rand();
508
509main(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++;
518again:
519	if (argc < 1) {
520usage:
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
565gausspage
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
577float	sqrt(), log(), rnd(), cos(), gauss();
578char	*valloc();
579int	rand();
580
581main(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++;
592again:
593	if (argc < 1) {
594usage:
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
649float
650gauss(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
660float
661rnd()
662{
663	static int seed = 1;
664	static int biggest = 0x7fffffff;
665
666	return ((float)rand(seed) / (float)biggest);
667}
668.vE