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