#include #include #include #include #include #include #include #include #include #include #include #define SECTORSIZE 512 #define READSIZE 512*20000*10 #define SMALLREADSIZE 512 #define NSEC_IN_SEC 1000000000UL #define NSEC_IN_MSEC 1000000UL void measure_one(int fd, off_t off) { struct timespec tstart, tend; char buf[READSIZE]; if (lseek(fd, off, SEEK_SET) < 0) err(1, "lseek"); if (clock_gettime(CLOCK_MONOTONIC, &tstart) != 0) err(1, "clock_gettime"); if (write(fd, buf, READSIZE) < 0) err(1, "read"); if (clock_gettime(CLOCK_MONOTONIC, &tend) != 0) err(1, "clock_gettime"); printf("off %lld: %lu ns\n", off, (((long)tend.tv_sec * NSEC_IN_SEC + tend.tv_nsec) - ((long)tstart.tv_sec * NSEC_IN_SEC + tstart.tv_nsec))); } void measure_seek(int fd, off_t start, off_t end) { struct timespec tstart, tend; char buf[READSIZE]; int i; #if 0 /* Try to flush the cache by doing large reads in the middle */ if (lseek(fd, (end - start) / 2, SEEK_SET) < 0) err(1, "lseek"); for (i = 0; i < 15; i++) { if (lseek(fd, (end - start) / 2, SEEK_SET) < 0) err(1, "lseek"); if (read(fd, buf, READSIZE) < 0) err(1, "read"); } #endif if (lseek(fd, start, SEEK_SET) < 0) err(1, "lseek"); if (write(fd, buf, SMALLREADSIZE) < 0) err(1, "read"); if (lseek(fd, end - SMALLREADSIZE, SEEK_SET) < 0) err(1, "lseek"); if (clock_gettime(CLOCK_MONOTONIC, &tstart) != 0) err(1, "clock_gettime"); if (write(fd, buf, SMALLREADSIZE) < 0) err(1, "read"); if (clock_gettime(CLOCK_MONOTONIC, &tend) != 0) err(1, "clock_gettime"); printf("distance %lld %lu ns\n", end - start, (((long)tend.tv_sec * NSEC_IN_SEC + tend.tv_nsec) - ((long)tstart.tv_sec * NSEC_IN_SEC + tstart.tv_nsec))); } void measure_seek2(int fd, off_t start, off_t end) { struct timespec tstart, tend; char buf[READSIZE]; off_t i, pos; if (lseek(fd, start, SEEK_SET) < 0) err(1, "lseek"); if (write(fd, buf, SMALLREADSIZE) < 0) err(1, "read"); for (i = 0;; i++) { if ((pos = lseek(fd, i * SMALLREADSIZE, SEEK_CUR)) < 0) err(1, "lseek"); if (pos > end) break; printf("pos %lld\n", pos); if (clock_gettime(CLOCK_MONOTONIC, &tstart) != 0) err(1, "clock_gettime"); if (write(fd, buf, SMALLREADSIZE) < 0) err(1, "read"); if (clock_gettime(CLOCK_MONOTONIC, &tend) != 0) err(1, "clock_gettime"); printf("distance2 %lld %lu ns\n", i * SMALLREADSIZE, (((long)tend.tv_sec * NSEC_IN_SEC + tend.tv_nsec) - ((long)tstart.tv_sec * NSEC_IN_SEC + tstart.tv_nsec))); } } int main(int argc, char **argv) { off_t mediasize, i; int fd, j, stride; if (argc < 4) { printf("Usage: %s \n", argv[0]); exit(1); } stride = atoi(argv[3]); if ((fd = open(argv[2], O_RDWR | O_DIRECT)) < 0) err(1, "open"); if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) != 0) err(1, "ioctl(DIOCMEDIASIZE)"); if (strcmp("stride", argv[1]) == 0) { printf("%lld blocks stride %d\n", mediasize / SECTORSIZE, stride); for (i = 0; i < mediasize / SECTORSIZE; i += stride) measure_one(fd, i * SECTORSIZE); return (0); } if (strcmp("seek2", argv[1]) == 0) { printf("seek2\n"); measure_seek2(fd, 0, mediasize); return (0); } for (i = 0; i < mediasize; i += READSIZE) for (j = 0; j < 5; j++) measure_seek(fd, 0, mediasize - i); return (0); }