2 * cc randread.c -o ~/bin/randread -O2 -lm
4 * randread device [bufsize:512 [range%:90 [nprocs:32]]]
9 #include <sys/sysctl.h>
13 #include <sys/errno.h>
21 #include <machine/atomic.h>
22 #include <machine/cpufunc.h>
24 typedef struct pdata {
37 main(int ac, char **av)
47 volatile pdata_t *pdata;
54 size_t tscfreq_size = sizeof(tscfreq);
56 sysctlbyname("hw.tsc_frequency", &tscfreq, &tscfreq_size, NULL, 0);
59 if (ac < 2 || ac > 5) {
60 fprintf(stderr, "%s <device> [bufsize:512 [range%:90 [nprocs:32]]]\n",
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");
75 range = strtod(av[3], NULL);
79 nprocs = strtol(av[4], NULL, 0);
80 if (nprocs < 0 || nprocs > 512) {
81 fprintf(stderr, "absurd nprocs (%d)\n", nprocs);
86 fd = open(av[1], O_RDONLY);
88 fprintf(stderr, "open %s: %s\n", av[1], strerror(errno));
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) {
105 fd = open(av[1], O_RDONLY);
110 pdata->lotime = 0x7FFFFFFFFFFFFFFFLL;
117 pdata->tsc_total1 = 0;
118 pdata->tsc_total2 = 0;
119 pdata->lotime = 0x7FFFFFFFFFFFFFFFLL;
124 pos = random() ^ ((long)random() << 31);
125 pos &= 0x7FFFFFFFFFFFFFFFLLU;
126 pos = (pos % limit) & ~(off_t)(bytes - 1);
128 read(fd, buf, bytes);
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;
158 lotime = pdata[0].lotime;
159 hitime = pdata[0].hitime;
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;
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);
186 stddev = stddev / (double)tscfreq; /* normalize to 1 second units */
189 printf("%6.0f/s avg=%6.2fuS bw=%-6.2fMB/s "
190 "lo=%-3.2fuS, hi=%-3.2fuS stddev=%3.2fuS\n",
193 (double)count * bytes / 1e6 / ((double)delta / (double)tscfreq),