inpcb: Use netisr_ncpus for listing inpcbs.
[dragonfly.git] / test / sysperf / randread.c
blobb500ebb5332e722466194da28f7a08207a703e2b
1 /*
2 * cc randread.c -o ~/bin/randread -O2 -lm
4 * randread device [bufsize:512 [range%:90 [nprocs:32]]]
6 * requires TSC
7 */
8 #include <sys/types.h>
9 #include <sys/sysctl.h>
10 #include <sys/stat.h>
11 #include <sys/file.h>
12 #include <sys/mman.h>
13 #include <sys/errno.h>
14 #include <sys/wait.h>
15 #include <string.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <math.h>
20 #include <assert.h>
21 #include <machine/atomic.h>
22 #include <machine/cpufunc.h>
24 typedef struct pdata {
25 int64_t counter;
26 int64_t lotime;
27 int64_t hitime;
28 int64_t tsc_total1;
29 int64_t tsc_total2;
30 int64_t unused00;
31 int64_t unused01;
32 int unused02;
33 int reset;
34 } pdata_t;
36 int
37 main(int ac, char **av)
39 char *buf;
40 size_t bytes = 512;
41 off_t limit;
42 int fd;
43 int i;
44 int loops;
45 int nprocs = 32;
46 double range = 90.0;
47 volatile pdata_t *pdata;
48 int64_t tsc1;
49 int64_t tsc2;
50 int64_t delta;
51 int64_t tscfreq = 0;
52 int64_t lotime;
53 int64_t hitime;
54 size_t tscfreq_size = sizeof(tscfreq);
56 sysctlbyname("hw.tsc_frequency", &tscfreq, &tscfreq_size, NULL, 0);
57 assert(tscfreq != 0);
59 if (ac < 2 || ac > 5) {
60 fprintf(stderr, "%s <device> [bufsize:512 [range%:90 [nprocs:32]]]\n",
61 av[0]);
62 exit (1);
65 if (ac >= 3) {
66 bytes = (size_t)strtoul(av[2], NULL, 0);
67 if (bytes < 512 || (bytes ^ (bytes - 1)) != ((bytes << 1) - 1)) {
68 fprintf(stderr, "bytes must be a power of 2 >= 512\n");
69 exit (1);
72 buf = malloc(bytes);
74 if (ac >= 4) {
75 range = strtod(av[3], NULL);
78 if (ac >= 5) {
79 nprocs = strtol(av[4], NULL, 0);
80 if (nprocs < 0 || nprocs > 512) {
81 fprintf(stderr, "absurd nprocs (%d)\n", nprocs);
82 exit(1);
86 fd = open(av[1], O_RDONLY);
87 if (fd < 0) {
88 fprintf(stderr, "open %s: %s\n", av[1], strerror(errno));
89 exit (1);
92 lseek(fd, 0L, 2);
93 limit = lseek(fd, 0L, 1);
94 limit = (off_t)((double)limit * range / 100.0);
95 limit &= ~(off_t)(bytes - 1);
96 printf("device %s bufsize %zd limit %4.3fGB nprocs %d\n",
97 av[1], bytes, (double)limit / (1024.0*1024.0*1024.0), nprocs);
99 pdata = mmap(NULL, nprocs * sizeof(*pdata), PROT_READ|PROT_WRITE,
100 MAP_SHARED|MAP_ANON, -1, 0);
102 for (i = 0; i < nprocs; ++i) {
103 if (fork() == 0) {
104 close(fd);
105 fd = open(av[1], O_RDONLY);
106 srandomdev();
107 pdata += i;
109 tsc2 = rdtsc();
110 pdata->lotime = 0x7FFFFFFFFFFFFFFFLL;
112 for (;;) {
113 long pos;
115 if (pdata->reset) {
116 pdata->counter = 0;
117 pdata->tsc_total1 = 0;
118 pdata->tsc_total2 = 0;
119 pdata->lotime = 0x7FFFFFFFFFFFFFFFLL;
120 pdata->hitime = 0;
121 pdata->reset = 0;
124 pos = random() ^ ((long)random() << 31);
125 pos &= 0x7FFFFFFFFFFFFFFFLLU;
126 pos = (pos % limit) & ~(off_t)(bytes - 1);
127 lseek(fd, pos, 0);
128 read(fd, buf, bytes);
129 tsc1 = tsc2;
130 tsc2 = rdtsc();
131 delta = tsc2 - tsc1;
132 ++pdata->counter;
133 pdata->tsc_total1 += delta;
134 pdata->tsc_total2 += delta * delta;
135 if (pdata->lotime > delta)
136 pdata->lotime = delta;
137 if (pdata->hitime < delta)
138 pdata->hitime = delta;
143 tsc2 = rdtsc();
144 loops = 0;
146 for (;;) {
147 int64_t count;
148 int64_t total1;
149 int64_t total2;
150 double v;
151 double lo;
152 double hi;
153 double s1;
154 double s2;
155 double stddev;
157 sleep(1);
158 lotime = pdata[0].lotime;
159 hitime = pdata[0].hitime;
160 total1 = 0;
161 total2 = 0;
162 count = 0;
164 for (i = 0; i < nprocs; ++i) {
165 count += pdata[i].counter;
166 total1 += pdata[i].tsc_total1;
167 total2 += pdata[i].tsc_total2;
168 if (lotime > pdata[i].lotime)
169 lotime = pdata[i].lotime;
170 if (hitime < pdata[i].hitime)
171 hitime = pdata[i].hitime;
172 pdata[i].reset = 1;
174 tsc1 = tsc2;
175 tsc2 = rdtsc();
176 delta = tsc2 - tsc1;
177 v = count * ((double)delta / (double)tscfreq);
178 lo = (double)lotime / (double)tscfreq;
179 hi = (double)hitime / (double)tscfreq;
181 s1 = ((double)total2 - (double)total1 * (double)total1 / (double)count) / ((double)count - 1);
182 if (s1 < 0.0)
183 stddev = -sqrt(-s1);
184 else
185 stddev = sqrt(s1);
186 stddev = stddev / (double)tscfreq; /* normalize to 1 second units */
188 if (loops) {
189 printf("%6.0f/s avg=%6.2fuS bw=%-6.2fMB/s "
190 "lo=%-3.2fuS, hi=%-3.2fuS stddev=%3.2fuS\n",
192 1e6 * nprocs / v,
193 (double)count * bytes / 1e6 / ((double)delta / (double)tscfreq),
194 lo * 1e6,
195 hi * 1e6,
196 stddev * 1e6);
198 ++loops;
200 return 0;