1 /* rawspeed 1.15 - Measure speed of a device. Author: Kees J. Bot
20 #define SECTOR_SIZE 512
21 #define BLK_MAX_SECTORS (sizeof(int) == 2 ? 32 : 64)
22 #define CHR_MAX_SECTORS (sizeof(int) == 2 ? 63 : 512)
23 #define ABS_MAX_SECTORS (INT_MAX / SECTOR_SIZE)
25 #define USEC (!__minix || __minix_vmd)
27 /* Any good random number generator around? */
28 #if __minix_vmd || __linux
38 void report(const char *label
)
40 fprintf(stderr
, "rawspeed: %s: %s\n", label
, strerror(errno
));
43 void fatal(const char *label
)
52 "Usage: rawspeed [-u unit] [-m max] [-t seconds] [-c] [-r limit] device\n");
54 " -u unit = best sector multiple (default 2)\n");
56 " -m max = read multiples of unit upto 'max' (default %d raw, %d file)\n",
57 CHR_MAX_SECTORS
, BLK_MAX_SECTORS
);
59 " -t seconds = time to run test (default 10)\n");
61 " -c = cache test: rewind after each read or write of max size\n");
63 " -r limit = random seeks upto sector 'limit' before reading or writing\n");
74 int main(int argc
, char **argv
)
76 int i
, fd
, n
= 0, unit
= -1, max
= -1, cache
= 0;
77 int size
, seconds
= 10;
80 struct timeval start_time
, end_time
;
81 struct timezone dummy
;
85 off_t nbytes
= 0, wbytes
= 0, randlimit
= 0;
90 for (i
= 1; i
< argc
&& argv
[i
][0] == '-' && argv
[i
][1] != 0; i
++) {
93 if (argv
[i
][1] == '-' && argv
[i
][2] == 0) { i
++; break; }
95 for (opt
= argv
[i
]+1; *opt
!= 0; opt
++) {
98 if (i
== argc
) usage();
99 wbytes
= atol(argv
[++i
]) * 1024;
100 if (wbytes
<= 0) usage();
103 if (i
== argc
) usage();
104 max
= atoi(argv
[++i
]);
105 if (max
<= 0 || max
> ABS_MAX_SECTORS
)
109 if (i
== argc
) usage();
110 unit
= atoi(argv
[++i
]);
111 if (unit
<= 0 || unit
> ABS_MAX_SECTORS
)
115 if (i
== argc
) usage();
116 seconds
= atoi(argv
[++i
]);
117 if (seconds
<= 0) usage();
123 if (i
== argc
) usage();
124 randlimit
= atol(argv
[++i
]);
125 if (randlimit
<= 0) usage();
133 if (i
!= argc
- 1) usage();
135 if (strcmp(argv
[i
], "-") == 0) {
136 fd
= wbytes
== 0 ? 0 : 1;
140 if ((fd
= open(device
,
141 wbytes
== 0 ? O_RDONLY
: O_WRONLY
| O_CREAT
, 0666)) < 0)
145 if (fstat(fd
, &st
) >= 0 && S_ISCHR(st
.st_mode
))
146 max
= CHR_MAX_SECTORS
;
148 max
= BLK_MAX_SECTORS
;
151 if (unit
< 0) unit
= max
> 1 ? 2 : 1;
153 if (unit
== 0) usage();
154 size
= unit
* SECTOR_SIZE
;
157 if ((chunk
= malloc((size_t) size
)) == nil
) {
158 fprintf(stderr
, "rawspeed: can't grab %d bytes: %s\n",
159 size
, strerror(errno
));
163 /* Touch the pages to get real memory sending other processes to swap.
165 memset((void *) chunk
, 0, (size_t) size
);
167 /* Clean the cache. */
170 signal(SIGALRM
, timeout
);
171 signal(SIGINT
, timeout
);
173 gettimeofday(&start_time
, &dummy
);
174 if (randlimit
!= 0) srand((int) (start_time
.tv_sec
& INT_MAX
));
176 start_time
= time((time_t *) nil
);
177 if (randlimit
!= 0) srand((int) (start_time
& INT_MAX
));
182 while (!done
&& (n
= write(fd
, chunk
, size
)) > 0
183 && (nbytes
+= n
) < wbytes
) {
184 if (cache
&& lseek(fd
, (off_t
) 0, SEEK_SET
) == -1)
186 if (randlimit
!= 0) {
187 if (lseek(fd
, (off_t
)
188 (rand() % randlimit
* size
),
196 while (!done
&& (n
= read(fd
, chunk
, size
)) > 0) {
198 if (cache
&& lseek(fd
, (off_t
) 0, SEEK_SET
) == -1)
200 if (randlimit
!= 0) {
201 if (lseek(fd
, (off_t
)
202 (rand() % randlimit
* size
),
211 gettimeofday(&end_time
, &dummy
);
212 tenthsec
= (end_time
.tv_sec
- start_time
.tv_sec
) * 10
213 + (end_time
.tv_usec
- start_time
.tv_usec
) / 100000;
215 tenthsec
= (time((time_t *) 0) - start_time
) * 10;
217 if (n
< 0 && errno
== EINTR
) n
= 0;
218 if (n
< 0) report(device
);
223 fprintf(stderr
, "%lld kB / %ld.%ld s = ",
224 (nbytes
+ 512) / 1024,
225 tenthsec
/ 10, tenthsec
% 10);
227 fprintf(stderr
, "infinite\n");
229 if (nbytes
> LONG_MAX
/ 100) {
230 seconds
= (tenthsec
+ 5) / 10;
231 kBpts
= (nbytes
+ 512L * seconds
)
233 fprintf(stderr
, "%lld kB/s\n", kBpts
);
235 kBpts
= (100 * nbytes
+ 512L * tenthsec
)
236 / (1024L * tenthsec
);
237 fprintf(stderr
, "%lld.%d kB/s\n",
238 kBpts
/10, (int)(kBpts
%10));
242 if (randlimit
!= 0 && tenthsec
>= 5) {
246 tenthms
= (tenthsec
* 1000 + nseeks
/2) / nseeks
;
249 "%lld seeks / %ld.%ld s = %lld seeks/s = %lld.%d ms/seek\n",
250 nseeks
, tenthsec
/ 10, tenthsec
% 10,
251 (nseeks
* 10 + tenthsec
/2) / tenthsec
,
252 tenthms
/ 10, (int)(tenthms
% 10));
254 for (rpm
= 3600; rpm
<= 7200; rpm
+= 1800) {
255 int rotms
= (10000L / 2 * 60 + rpm
/2) / rpm
;
257 if (tenthms
<= rotms
) continue;
261 "discarding av. rotational delay:\n ");
264 fprintf(stderr
, ", ");
266 fprintf(stderr
, "%lld.%d ms (%d rpm)",
267 (tenthms
- rotms
) / 10,
268 (int)((tenthms
- rotms
) % 10),
271 if (disc
) fputc('\n', stdout
);
273 return n
< 0 ? 1 : 0;