/* * SEEKBENCH.C * * cc seekbench.c -o /tmp/sb * * This intentionally performs a sequence of seek/reads with ever * growing distances in a way that should be essentially uncached. * It attempts to defeat both OS caches and the HDs zone cache. * * The average read-latency per seek/read is calculated. * * This can heat up the hard drive so be careful. */ #include #include #include #include #include #include #include #include #define BLKSIZE ((intmax_t)1024) #define BLKMASK (BLKSIZE - 1) char Buf[BLKSIZE]; int main(int ac, char **av) { struct timeval tv1; struct timeval tv2; off_t bytes; off_t base; off_t skip; intmax_t us; int fd; int count; if (ac == 1) { fprintf(stderr, "seekbench \n"); exit(1); } fd = open(av[1], O_RDONLY); if (fd < 0) { perror("open"); exit(1); } lseek(fd, 0L, 2); bytes = lseek(fd, 0L, 1); printf("%s: %jdMB\n", av[1], (intmax_t)bytes / 1024 / 1024); printf("distance avg-seek\n"); skip = BLKSIZE; while (skip < bytes) { count = 0; gettimeofday(&tv1, NULL); for (base = skip; base < bytes && count < 100; base += skip) { lseek(fd, base, 0); read(fd, Buf, BLKSIZE); ++count; } gettimeofday(&tv2, NULL); us = (tv2.tv_usec + 1000000 - tv1.tv_usec) + (tv2.tv_sec - 1 - tv1.tv_sec) * 1000000; if (skip < 100*1024*1024) printf("%5jdKB %6.3fms\n", (intmax_t)skip / 1024, (double)us / 1000.0 / count); else printf("%5jdMB %6.3fms\n", (intmax_t)skip / 1024 / 1024, (double)us / 1000.0 / count); skip += BLKSIZE; if (skip < BLKSIZE * 25) skip += BLKSIZE; else skip += (skip / 25 + BLKMASK) & ~BLKMASK; } }