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
),