1 /*******************************************************************************
2 * The BYTE UNIX Benchmarks - Release 3
3 * Module: fstime.c SID: 3.5 5/15/91 19:30:19
5 *******************************************************************************
6 * Bug reports, patches, comments, suggestions should be sent to:
8 * Ben Smith, Rick Grehan or Tom Yager
9 * ben@bytepb.byte.com rick_g@bytepb.byte.com tyager@bytepb.byte.com
11 *******************************************************************************
13 * $Header: fstime.c,v 3.4 87/06/22 14:23:05 kjmcdonell Beta $
14 * 10/19/89 - rewrote timing calcs and added clock check (Ben Smith)
15 * 10/26/90 - simplify timing, change defaults (Tom Yager)
16 * 11/16/90 - added better error handling and changed output format (Ben Smith)
17 * 11/17/90 - changed the whole thing around (Ben Smith)
18 * 2/22/91 - change a few style elements and improved error handling (Ben Smith)
19 * 4/17/91 - incorporated suggestions from Seckin Unlu (seckin@sumac.intel.com)
20 * 4/17/91 - limited size of file, will rewind when reaches end of file
21 * 7/95 - fixed mishandling of read() and write() return codes
22 * Carl Emilio Prelz <fluido@telepac.pt>
23 * 12/95 - Massive changes. Made sleep time proportional increase with run
24 * time; added fsbuffer and fsdisk variants; added partial counting
25 * of partial reads/writes (was *full* credit); added dual syncs.
26 * David C Niemi <niemi@tux.org>
27 * 10/22/97 - code cleanup to remove ANSI C compiler warnings
28 * Andy Kahn <kahn@zk3.dec.com>
29 * 9/24/07 - Separate out the read and write tests;
30 * output the actual time used in the results.
31 * Ian Smith <johantheghost at yahoo period com>
32 ******************************************************************************/
33 char SCCSid
[] = "@(#) @(#)fstime.c:3.5 -- 5/15/91 19:30:19";
45 #define MAX_BUFSIZE 8192
47 /* This must be set to the smallest BUFSIZE or 1024, whichever is smaller */
49 #define HALFCOUNT (COUNTSIZE/2) /* Half of COUNTSIZE */
51 #define FNAME0 "dummy0"
52 #define FNAME1 "dummy1"
55 extern void sync(void);
57 extern int sync(void);
60 int w_test(int timeSecs
);
61 int r_test(int timeSecs
);
62 int c_test(int timeSecs
);
64 long read_score
= 1, write_score
= 1, copy_score
= 1;
66 /****************** GLOBALS ***************************/
68 /* The buffer size for the tests. */
72 * The max number of 1024-byte blocks in the file.
73 * Don't limit it much, so that memory buffering
76 int max_blocks
= 2000;
78 /* The max number of BUFSIZE blocks in the file. */
81 /* Countable units per 1024 bytes */
84 /* Countable units per bufsize */
87 /* The actual buffer. */
89 /* Let's carry on using a static buffer for this, like older versions
90 * of the code did. It turns out that if you use a malloc buffer,
91 * it goes 50% slower on reads, when using a 4k buffer -- at least on
92 * my OpenSUSE 10.2 system.
95 char buf
[MAX_BUFSIZE
];
100 void stop_count(int);
104 /******************** MAIN ****************************/
106 int main(int argc
, char *argv
[])
108 /* The number of seconds to run for. */
109 int seconds
= SECONDS
;
111 /* The type of test to run. */
117 for (i
= 1; i
< argc
; ++i
) {
118 if (argv
[i
][0] == '-') {
119 switch (argv
[i
][1]) {
126 bufsize
= atoi(argv
[++i
]);
129 max_blocks
= atoi(argv
[++i
]);
132 seconds
= atoi(argv
[++i
]);
135 if (chdir(argv
[++i
]) < 0) {
136 perror("fstime: chdir");
141 fprintf(stderr
, "Usage: fstime [-c|-r|-w] [-b <bufsize>] [-m <max_blocks>] [-t <seconds>]\n");
145 fprintf(stderr
, "Usage: fstime [-c|-r|-w] [-b <bufsize>] [-m <max_blocks>] [-t <seconds>]\n");
150 if (bufsize
< COUNTSIZE
|| bufsize
> MAX_BUFSIZE
) {
151 fprintf(stderr
, "fstime: buffer size must be in range %d-%d\n",
152 COUNTSIZE
, 1024*1024);
155 if (max_blocks
< 1 || max_blocks
> 1024*1024) {
156 fprintf(stderr
, "fstime: max blocks must be in range %d-%d\n",
160 if (seconds
< 1 || seconds
> 3600) {
161 fprintf(stderr
, "fstime: time must be in range %d-%d seconds\n",
166 max_buffs
= max_blocks
* 1024 / bufsize
;
167 count_per_k
= 1024 / COUNTSIZE
;
168 count_per_buf
= bufsize
/ COUNTSIZE
;
171 if ((buf = malloc(bufsize)) == 0) {
172 fprintf(stderr, "fstime: failed to malloc %d bytes\n", bufsize);
177 if((f
= creat(FNAME0
, 0600)) == -1) {
178 perror("fstime: creat");
183 if((g
= creat(FNAME1
, 0600)) == -1) {
184 perror("fstime: creat");
189 if( (f
= open(FNAME0
, 2)) == -1) {
190 perror("fstime: open");
193 if( ( g
= open(FNAME1
, 2)) == -1 ) {
194 perror("fstime: open");
199 for (i
=0; i
< bufsize
; ++i
)
202 signal(SIGKILL
,clean_up
);
205 * Run the selected test.
206 * When I got here, this program ran full 30-second tests for
207 * write, read, and copy, outputting the results for each. BUT
208 * only the copy results are actually used in the benchmark index.
209 * With multiple iterations and three sets of FS tests, that amounted
210 * to about 10 minutes of wasted time per run.
212 * So, I've made the test selectable. Except that the read and write
213 * passes are used to create the test file and calibrate the rates used
214 * to tweak the results of the copy test. So, for copy tests, we do
215 * a few seconds of write and read to prime the pump.
217 * Note that this will also pull the file into the FS cache on any
218 * modern system prior to the copy test. Whether this is good or
219 * bad is a matter of perspective, but it's how it was when I got
222 * Ian Smith <johantheghost at yahoo period com> 21 Sep 2007
226 status
= w_test(seconds
);
230 status
= r_test(seconds
);
235 status
= c_test(seconds
);
238 fprintf(stderr
, "fstime: unknown test \'%c\'\n", test
);
251 static double getFloatTime(void)
256 return (double) t
.tv_sec
+ (double) t
.tv_usec
/ 1000000.0;
261 * Run the write test for the time given in seconds.
263 int w_test(int timeSecs
)
265 unsigned long counted
= 0L;
271 /* Sync and let it settle */
279 signal(SIGALRM
, stop_count
);
282 start
= getFloatTime();
285 for(f_blocks
=0; f_blocks
< max_buffs
; ++f_blocks
) {
286 if ((tmp
=write(f
, buf
, bufsize
)) != bufsize
) {
287 if (errno
!= EINTR
) {
288 perror("fstime: write");
292 counted
+= ((tmp
+HALFCOUNT
)/COUNTSIZE
);
294 counted
+= count_per_buf
;
296 lseek(f
, 0L, 0); /* rewind */
300 end
= getFloatTime();
301 write_score
= (long) ((double) counted
/ ((end
- start
) * count_per_k
));
302 printf("Write done: %ld in %.4f, score %ld\n",
303 counted
, end
- start
, write_score
);
306 * Output the test results. Use the true time.
308 fprintf(stderr
, "COUNT|%ld|0|KBps\n", write_score
);
309 fprintf(stderr
, "TIME|%.1f\n", end
- start
);
315 * Run the read test for the time given in seconds.
317 int r_test(int timeSecs
)
319 unsigned long counted
= 0L;
325 /* Sync and let it settle */
337 signal(SIGALRM
, stop_count
);
340 start
= getFloatTime();
343 /* read while checking for an error */
344 if ((tmp
=read(f
, buf
, bufsize
)) != bufsize
) {
348 lseek(f
, 0L, 0); /* rewind at end of file */
349 counted
+= (tmp
+HALFCOUNT
)/COUNTSIZE
;
353 counted
+= (tmp
+HALFCOUNT
)/COUNTSIZE
;
356 perror("fstime: read");
361 counted
+= count_per_buf
;
365 end
= getFloatTime();
366 read_score
= (long) ((double) counted
/ ((end
- start
) * count_per_k
));
367 printf("Read done: %ld in %.4f, score %ld\n",
368 counted
, end
- start
, read_score
);
371 * Output the test results. Use the true time.
373 fprintf(stderr
, "COUNT|%ld|0|KBps\n", read_score
);
374 fprintf(stderr
, "TIME|%.1f\n", end
- start
);
381 * Run the copy test for the time given in seconds.
383 int c_test(int timeSecs
)
385 unsigned long counted
= 0L;
401 signal(SIGALRM
, stop_count
);
404 start
= getFloatTime();
407 if ((tmp
=read(f
, buf
, bufsize
)) != bufsize
) {
411 lseek(f
, 0L, 0); /* rewind at end of file */
412 lseek(g
, 0L, 0); /* rewind the output too */
415 /* part credit for leftover bytes read */
416 counted
+= ( (tmp
* write_score
) /
417 (read_score
+ write_score
)
418 + HALFCOUNT
) / COUNTSIZE
;
422 perror("fstime: copy read");
427 if ((tmp
=write(g
, buf
, bufsize
)) != bufsize
) {
428 if (errno
!= EINTR
) {
429 perror("fstime: copy write");
433 /* Full credit for part of buffer written */
436 /* Plus part credit having read full buffer */
437 ( ((bufsize
- tmp
) * write_score
) /
438 (read_score
+ write_score
) )
439 + HALFCOUNT
) / COUNTSIZE
;
442 counted
+= count_per_buf
;
447 end
= getFloatTime();
448 copy_score
= (long) ((double) counted
/ ((end
- start
) * count_per_k
));
449 printf("Copy done: %ld in %.4f, score %ld\n",
450 counted
, end
- start
, copy_score
);
453 * Output the test results. Use the true time.
455 fprintf(stderr
, "COUNT|%ld|0|KBps\n", copy_score
);
456 fprintf(stderr
, "TIME|%.1f\n", end
- start
);
461 void stop_count(int sig
)
467 void clean_up(int sig
)