/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

  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. if (argc < 2) {
  66. printf("usage: %s #syscalls\n", argv[0]);
  67. exit(1);
  68. }
  69. ncalls = atoi(argv[1]);
  70. while (ncalls-- > 0)
  71. (void) getpid();
  72. }
  73. .vE
  74. .SH
  75. csw
  76. .LP
  77. .vS
  78. /*
  79. * Context switching benchmark.
  80. *
  81. * Force system to context switch 2*nsigs
  82. * times by forking and exchanging signals.
  83. * To calculate system overhead for a context
  84. * switch, the signocsw program must be run
  85. * with nsigs. Overhead is then estimated by
  86. * t1 = time csw <n>
  87. * t2 = time signocsw <n>
  88. * overhead = t1 - 2 * t2;
  89. */
  90. #include <signal.h>
  91. int sigsub();
  92. int otherpid;
  93. int nsigs;
  94. main(argc, argv)
  95. char *argv[];
  96. {
  97. int pid;
  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. sigsub()
  114. {
  115. signal(SIGALRM, sigsub);
  116. kill(otherpid, SIGALRM);
  117. if (--nsigs <= 0)
  118. exit(0);
  119. }
  120. .vE
  121. .SH
  122. signocsw
  123. .LP
  124. .vS
  125. /*
  126. * Signal without context switch benchmark.
  127. */
  128. #include <signal.h>
  129. int pid;
  130. int nsigs;
  131. int sigsub();
  132. main(argc, argv)
  133. char *argv[];
  134. {
  135. register int i;
  136. if (argc < 2) {
  137. printf("usage: %s nsignals\n", argv[0]);
  138. exit(1);
  139. }
  140. nsigs = atoi(argv[1]);
  141. signal(SIGALRM, sigsub);
  142. pid = getpid();
  143. for (i = 0; i < nsigs; i++)
  144. kill(pid, SIGALRM);
  145. }
  146. sigsub()
  147. {
  148. signal(SIGALRM, sigsub);
  149. }
  150. .vE
  151. .SH
  152. pipeself
  153. .LP
  154. .vS
  155. /*
  156. * IPC benchmark,
  157. * write to self using pipes.
  158. */
  159. main(argc, argv)
  160. char *argv[];
  161. {
  162. char buf[512];
  163. int fd[2], msgsize;
  164. register int i, iter;
  165. if (argc < 3) {
  166. printf("usage: %s iterations message-size\n", argv[0]);
  167. exit(1);
  168. }
  169. argc--, argv++;
  170. iter = atoi(*argv);
  171. argc--, argv++;
  172. msgsize = atoi(*argv);
  173. if (msgsize > sizeof (buf) || msgsize <= 0) {
  174. printf("%s: Bad message size.\n", *argv);
  175. exit(2);
  176. }
  177. if (pipe(fd) < 0) {
  178. perror("pipe");
  179. exit(3);
  180. }
  181. for (i = 0; i < iter; i++) {
  182. write(fd[1], buf, msgsize);
  183. read(fd[0], buf, msgsize);
  184. }
  185. }
  186. .vE
  187. .SH
  188. pipediscard
  189. .LP
  190. .vS
  191. /*
  192. * IPC benchmarkl,
  193. * write and discard using pipes.
  194. */
  195. main(argc, argv)
  196. char *argv[];
  197. {
  198. char buf[512];
  199. int fd[2], msgsize;
  200. register int i, iter;
  201. if (argc < 3) {
  202. printf("usage: %s iterations message-size\n", argv[0]);
  203. exit(1);
  204. }
  205. argc--, argv++;
  206. iter = atoi(*argv);
  207. argc--, argv++;
  208. msgsize = atoi(*argv);
  209. if (msgsize > sizeof (buf) || msgsize <= 0) {
  210. printf("%s: Bad message size.\n", *argv);
  211. exit(2);
  212. }
  213. if (pipe(fd) < 0) {
  214. perror("pipe");
  215. exit(3);
  216. }
  217. if (fork() == 0)
  218. for (i = 0; i < iter; i++)
  219. read(fd[0], buf, msgsize);
  220. else
  221. for (i = 0; i < iter; i++)
  222. write(fd[1], buf, msgsize);
  223. }
  224. .vE
  225. .SH
  226. pipeback
  227. .LP
  228. .vS
  229. /*
  230. * IPC benchmark,
  231. * read and reply using pipes.
  232. *
  233. * Process forks and exchanges messages
  234. * over a pipe in a request-response fashion.
  235. */
  236. main(argc, argv)
  237. char *argv[];
  238. {
  239. char buf[512];
  240. int fd[2], fd2[2], msgsize;
  241. register int i, iter;
  242. if (argc < 3) {
  243. printf("usage: %s iterations message-size\n", argv[0]);
  244. exit(1);
  245. }
  246. argc--, argv++;
  247. iter = atoi(*argv);
  248. argc--, argv++;
  249. msgsize = atoi(*argv);
  250. if (msgsize > sizeof (buf) || msgsize <= 0) {
  251. printf("%s: Bad message size.\n", *argv);
  252. exit(2);
  253. }
  254. if (pipe(fd) < 0) {
  255. perror("pipe");
  256. exit(3);
  257. }
  258. if (pipe(fd2) < 0) {
  259. perror("pipe");
  260. exit(3);
  261. }
  262. if (fork() == 0)
  263. for (i = 0; i < iter; i++) {
  264. read(fd[0], buf, msgsize);
  265. write(fd2[1], buf, msgsize);
  266. }
  267. else
  268. for (i = 0; i < iter; i++) {
  269. write(fd[1], buf, msgsize);
  270. read(fd2[0], buf, msgsize);
  271. }
  272. }
  273. .vE
  274. .SH
  275. forks
  276. .LP
  277. .vS
  278. /*
  279. * Benchmark program to calculate fork+wait
  280. * overhead (approximately). Process
  281. * forks and exits while parent waits.
  282. * The time to run this program is used
  283. * in calculating exec overhead.
  284. */
  285. main(argc, argv)
  286. char *argv[];
  287. {
  288. register int nforks, i;
  289. char *cp;
  290. int pid, child, status, brksize;
  291. if (argc < 2) {
  292. printf("usage: %s number-of-forks sbrk-size\n", argv[0]);
  293. exit(1);
  294. }
  295. nforks = atoi(argv[1]);
  296. if (nforks < 0) {
  297. printf("%s: bad number of forks\n", argv[1]);
  298. exit(2);
  299. }
  300. brksize = atoi(argv[2]);
  301. if (brksize < 0) {
  302. printf("%s: bad size to sbrk\n", argv[2]);
  303. exit(3);
  304. }
  305. cp = (char *)sbrk(brksize);
  306. if ((int)cp == -1) {
  307. perror("sbrk");
  308. exit(4);
  309. }
  310. for (i = 0; i < brksize; i += 1024)
  311. cp[i] = i;
  312. while (nforks-- > 0) {
  313. child = fork();
  314. if (child == -1) {
  315. perror("fork");
  316. exit(-1);
  317. }
  318. if (child == 0)
  319. _exit(-1);
  320. while ((pid = wait(&status)) != -1 && pid != child)
  321. ;
  322. }
  323. exit(0);
  324. }
  325. .vE
  326. .SH
  327. execs
  328. .LP
  329. .vS
  330. /*
  331. * Benchmark program to calculate exec
  332. * overhead (approximately). Process
  333. * forks and execs "null" test program.
  334. * The time to run the fork program should
  335. * then be deducted from this one to
  336. * estimate the overhead for the exec.
  337. */
  338. main(argc, argv)
  339. char *argv[];
  340. {
  341. register int nexecs, i;
  342. char *cp, *sbrk();
  343. int pid, child, status, brksize;
  344. if (argc < 3) {
  345. printf("usage: %s number-of-execs sbrk-size job-name\n",
  346. argv[0]);
  347. exit(1);
  348. }
  349. nexecs = atoi(argv[1]);
  350. if (nexecs < 0) {
  351. printf("%s: bad number of execs\n", argv[1]);
  352. exit(2);
  353. }
  354. brksize = atoi(argv[2]);
  355. if (brksize < 0) {
  356. printf("%s: bad size to sbrk\n", argv[2]);
  357. exit(3);
  358. }
  359. cp = sbrk(brksize);
  360. if ((int)cp == -1) {
  361. perror("sbrk");
  362. exit(4);
  363. }
  364. for (i = 0; i < brksize; i += 1024)
  365. cp[i] = i;
  366. while (nexecs-- > 0) {
  367. child = fork();
  368. if (child == -1) {
  369. perror("fork");
  370. exit(-1);
  371. }
  372. if (child == 0) {
  373. execv(argv[3], argv);
  374. perror("execv");
  375. _exit(-1);
  376. }
  377. while ((pid = wait(&status)) != -1 && pid != child)
  378. ;
  379. }
  380. exit(0);
  381. }
  382. .vE
  383. .SH
  384. nulljob
  385. .LP
  386. .vS
  387. /*
  388. * Benchmark "null job" program.
  389. */
  390. main(argc, argv)
  391. char *argv[];
  392. {
  393. exit(0);
  394. }
  395. .vE
  396. .SH
  397. bigjob
  398. .LP
  399. .vS
  400. /*
  401. * Benchmark "null big job" program.
  402. */
  403. /* 250 here is intended to approximate vi's text+data size */
  404. char space[1024 * 250] = "force into data segment";
  405. main(argc, argv)
  406. char *argv[];
  407. {
  408. exit(0);
  409. }
  410. .vE
  411. .bp
  412. .SH
  413. seqpage
  414. .LP
  415. .vS
  416. /*
  417. * Sequential page access benchmark.
  418. */
  419. #include <sys/vadvise.h>
  420. char *valloc();
  421. main(argc, argv)
  422. char *argv[];
  423. {
  424. register i, niter;
  425. register char *pf, *lastpage;
  426. int npages = 4096, pagesize, vflag = 0;
  427. char *pages, *name;
  428. name = argv[0];
  429. argc--, argv++;
  430. again:
  431. if (argc < 1) {
  432. usage:
  433. printf("usage: %s [ -v ] [ -p #pages ] niter\n", name);
  434. exit(1);
  435. }
  436. if (strcmp(*argv, "-p") == 0) {
  437. argc--, argv++;
  438. if (argc < 1)
  439. goto usage;
  440. npages = atoi(*argv);
  441. if (npages <= 0) {
  442. printf("%s: Bad page count.\n", *argv);
  443. exit(2);
  444. }
  445. argc--, argv++;
  446. goto again;
  447. }
  448. if (strcmp(*argv, "-v") == 0) {
  449. argc--, argv++;
  450. vflag++;
  451. goto again;
  452. }
  453. niter = atoi(*argv);
  454. pagesize = getpagesize();
  455. pages = valloc(npages * pagesize);
  456. if (pages == (char *)0) {
  457. printf("Can't allocate %d pages (%2.1f megabytes).\n",
  458. npages, (npages * pagesize) / (1024. * 1024.));
  459. exit(3);
  460. }
  461. lastpage = pages + (npages * pagesize);
  462. if (vflag)
  463. vadvise(VA_SEQL);
  464. for (i = 0; i < niter; i++)
  465. for (pf = pages; pf < lastpage; pf += pagesize)
  466. *pf = 1;
  467. }
  468. .vE
  469. .SH
  470. randpage
  471. .LP
  472. .vS
  473. /*
  474. * Random page access benchmark.
  475. */
  476. #include <sys/vadvise.h>
  477. char *valloc();
  478. int rand();
  479. main(argc, argv)
  480. char *argv[];
  481. {
  482. register int npages = 4096, pagesize, pn, i, niter;
  483. int vflag = 0, debug = 0;
  484. char *pages, *name;
  485. name = argv[0];
  486. argc--, argv++;
  487. again:
  488. if (argc < 1) {
  489. usage:
  490. printf("usage: %s [ -d ] [ -v ] [ -p #pages ] niter\n", name);
  491. exit(1);
  492. }
  493. if (strcmp(*argv, "-p") == 0) {
  494. argc--, argv++;
  495. if (argc < 1)
  496. goto usage;
  497. npages = atoi(*argv);
  498. if (npages <= 0) {
  499. printf("%s: Bad page count.\n", *argv);
  500. exit(2);
  501. }
  502. argc--, argv++;
  503. goto again;
  504. }
  505. if (strcmp(*argv, "-v") == 0) {
  506. argc--, argv++;
  507. vflag++;
  508. goto again;
  509. }
  510. if (strcmp(*argv, "-d") == 0) {
  511. argc--, argv++;
  512. debug++;
  513. goto again;
  514. }
  515. niter = atoi(*argv);
  516. pagesize = getpagesize();
  517. pages = valloc(npages * pagesize);
  518. if (pages == (char *)0) {
  519. printf("Can't allocate %d pages (%2.1f megabytes).\n",
  520. npages, (npages * pagesize) / (1024. * 1024.));
  521. exit(3);
  522. }
  523. if (vflag)
  524. vadvise(VA_ANOM);
  525. for (i = 0; i < niter; i++) {
  526. pn = random() % npages;
  527. if (debug)
  528. printf("touch page %d\n", pn);
  529. pages[pagesize * pn] = 1;
  530. }
  531. }
  532. .vE
  533. .SH
  534. gausspage
  535. .LP
  536. .vS
  537. /*
  538. * Random page access with
  539. * a gaussian distribution.
  540. *
  541. * Allocate a large (zero fill on demand) address
  542. * space and fault the pages in a random gaussian
  543. * order.
  544. */
  545. float sqrt(), log(), rnd(), cos(), gauss();
  546. char *valloc();
  547. int rand();
  548. main(argc, argv)
  549. char *argv[];
  550. {
  551. register int pn, i, niter, delta;
  552. register char *pages;
  553. float sd = 10.0;
  554. int npages = 4096, pagesize, debug = 0;
  555. char *name;
  556. name = argv[0];
  557. argc--, argv++;
  558. again:
  559. if (argc < 1) {
  560. usage:
  561. printf(
  562. "usage: %s [ -d ] [ -p #pages ] [ -s standard-deviation ] iterations\n", name);
  563. exit(1);
  564. }
  565. if (strcmp(*argv, "-s") == 0) {
  566. argc--, argv++;
  567. if (argc < 1)
  568. goto usage;
  569. sscanf(*argv, "%f", &sd);
  570. if (sd <= 0) {
  571. printf("%s: Bad standard deviation.\n", *argv);
  572. exit(2);
  573. }
  574. argc--, argv++;
  575. goto again;
  576. }
  577. if (strcmp(*argv, "-p") == 0) {
  578. argc--, argv++;
  579. if (argc < 1)
  580. goto usage;
  581. npages = atoi(*argv);
  582. if (npages <= 0) {
  583. printf("%s: Bad page count.\n", *argv);
  584. exit(2);
  585. }
  586. argc--, argv++;
  587. goto again;
  588. }
  589. if (strcmp(*argv, "-d") == 0) {
  590. argc--, argv++;
  591. debug++;
  592. goto again;
  593. }
  594. niter = atoi(*argv);
  595. pagesize = getpagesize();
  596. pages = valloc(npages*pagesize);
  597. if (pages == (char *)0) {
  598. printf("Can't allocate %d pages (%2.1f megabytes).\n",
  599. npages, (npages*pagesize) / (1024. * 1024.));
  600. exit(3);
  601. }
  602. pn = 0;
  603. for (i = 0; i < niter; i++) {
  604. delta = gauss(sd, 0.0);
  605. while (pn + delta < 0 || pn + delta > npages)
  606. delta = gauss(sd, 0.0);
  607. pn += delta;
  608. if (debug)
  609. printf("touch page %d\n", pn);
  610. else
  611. pages[pn * pagesize] = 1;
  612. }
  613. }
  614. float
  615. gauss(sd, mean)
  616. float sd, mean;
  617. {
  618. register float qa, qb;
  619. qa = sqrt(log(rnd()) * -2.0);
  620. qb = 3.14159 * rnd();
  621. return (qa * cos(qb) * sd + mean);
  622. }
  623. float
  624. rnd()
  625. {
  626. static int seed = 1;
  627. static int biggest = 0x7fffffff;
  628. return ((float)rand(seed) / (float)biggest);
  629. }
  630. .vE