xref: /dragonfly/test/debug/seekbench.c (revision 0db87cb7)
1 /*
2  * SEEKBENCH.C
3  *
4  * cc seekbench.c -o /tmp/sb
5  *
6  * This intentionally performs a sequence of seek/reads with ever
7  * growing distances in a way that should be essentially uncached.
8  * It attempts to defeat both OS caches and the HDs zone cache.
9  *
10  * The average read-latency per seek/read is calculated.
11  *
12  * This can heat up the hard drive so be careful.
13  */
14 
15 #include <sys/types.h>
16 #include <sys/time.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <stdarg.h>
21 #include <fcntl.h>
22 #include <libutil.h>
23 
24 #define BLKSIZE		((intmax_t)1024)
25 #define BLKMASK		(BLKSIZE - 1)
26 
27 char Buf[BLKSIZE];
28 
29 int
30 main(int ac, char **av)
31 {
32 	struct timeval tv1;
33 	struct timeval tv2;
34 	off_t bytes;
35 	off_t base;
36 	off_t skip;
37 	intmax_t us;
38 	int fd;
39 	int count;
40 
41 	if (ac == 1) {
42 		fprintf(stderr, "seekbench <blockdevice>\n");
43 		exit(1);
44 	}
45 	fd = open(av[1], O_RDONLY);
46 	if (fd < 0) {
47 		perror("open");
48 		exit(1);
49 	}
50 	lseek(fd, 0L, 2);
51 	bytes = lseek(fd, 0L, 1);
52 	printf("%s: %jdMB\n", av[1], (intmax_t)bytes / 1024 / 1024);
53 	printf("distance avg-seek\n");
54 	skip = BLKSIZE;
55 	while (skip < bytes) {
56 		count = 0;
57 		gettimeofday(&tv1, NULL);
58 		for (base = skip; base < bytes && count < 100; base += skip) {
59 			lseek(fd, base, 0);
60 			read(fd, Buf, BLKSIZE);
61 			++count;
62 		}
63 		gettimeofday(&tv2, NULL);
64 		us = (tv2.tv_usec + 1000000 - tv1.tv_usec) +
65 		     (tv2.tv_sec - 1 - tv1.tv_sec) * 1000000;
66 		if (skip < 100*1024*1024)
67 			printf("%5jdKB %6.3fms\n",
68 				(intmax_t)skip / 1024,
69 				(double)us / 1000.0 / count);
70 		else
71 			printf("%5jdMB %6.3fms\n",
72 				(intmax_t)skip / 1024 / 1024,
73 				(double)us / 1000.0 / count);
74 		skip += BLKSIZE;
75 		if (skip < BLKSIZE * 25)
76 			skip += BLKSIZE;
77 		else
78 			skip += (skip / 25 + BLKMASK) & ~BLKMASK;
79 	}
80 }
81