libefivar: Fix (instead of silence) the remaining warnings in libefivar.
[dragonfly.git] / test / sysperf / randread.c
1 /*
2  * cc randread.c -o ~/bin/randread -O2 -lm
3  *
4  * randread device [bufsize:512 [range%:90 [nprocs:32]]]
5  *
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>
23
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;
35
36 int
37 main(int ac, char **av)
38 {
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);
55
56     sysctlbyname("hw.tsc_frequency", &tscfreq, &tscfreq_size, NULL, 0);
57     assert(tscfreq != 0);
58
59     if (ac < 2 || ac > 5) {
60         fprintf(stderr, "%s <device> [bufsize:512 [range%:90 [nprocs:32]]]\n",
61                 av[0]);
62         exit (1);
63     }
64
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);
70         }
71     }
72     buf = malloc(bytes);
73
74     if (ac >= 4) {
75         range = strtod(av[3], NULL);
76     }
77
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);
83         }
84     }
85
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);
90     }
91
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);
98
99     pdata = mmap(NULL, nprocs * sizeof(*pdata), PROT_READ|PROT_WRITE,
100                     MAP_SHARED|MAP_ANON, -1, 0);
101
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;
108
109             tsc2 = rdtsc();
110             pdata->lotime = 0x7FFFFFFFFFFFFFFFLL;
111
112             for (;;) {
113                 long pos;
114
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;
122                 }
123
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;
139             }
140         }
141     }
142
143     tsc2 = rdtsc();
144     loops = 0;
145
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;
156
157         sleep(1);
158         lotime = pdata[0].lotime;
159         hitime = pdata[0].hitime;
160         total1 = 0;
161         total2 = 0;
162         count = 0;
163
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;
173         }
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;
180
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 */
187
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",
191                        v,
192                        1e6 * nprocs / v,
193                        (double)count * bytes / 1e6 / ((double)delta / (double)tscfreq),
194                        lo * 1e6,
195                        hi * 1e6,
196                        stddev * 1e6);
197         }
198         ++loops;
199     }
200     return 0;
201 }