#include #include #include #include #include #include #include #include #include #include #include #include #include #define KB(a) (a*1024) #define MB(a) (KB(a)*1024) static void usage(char *s) { fprintf(stderr, "Usage: %s [-v] [-N] -s -n iter " "[-d delta] [-c count]\n", s); fprintf(stderr, "\t-v:\t\tVerbose mode\n" "\t-N:\t\tNormalize results by number of reads\n" "\t-s :\tWorking set size (may specify K,M,G suffix)\n" "\t-n iter:\tNumber of test iterations\n" "\t-f filename:\tName of the file to read from\n" "\t-d [+|-]delta:\tDistance between subsequent reads\n" "\t-c count:\tNumber of reads\n" "\t-h:\t\tPrint this help\n" ); exit(1); } #define ABS(x) ((x) >= 0 ? (x) : -(x)) static void format_num(size_t v, size_t *new, char *code) { if (v % (1024 * 1024 * 1024) == 0) { *new = v / (1024 * 1024 * 1024); *code = 'G'; } else if (v % (1024 * 1024) == 0) { *new = v / (1024 * 1024); *code = 'M'; } else if (v % (1024) == 0) { *new = v / (1024); *code = 'K'; } else { *new = v; *code = ' '; } } static size_t parse_num(char *s) { size_t v = 0; for (;;) { switch (tolower(*s)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': v = v * 10 + *s - '0'; ++s; continue; case 'k': v *= 1024; return (v); case 'm': v *= (1024 * 1024); return (v); case 'g': v *= (1024 * 1024 * 1024); return (v); default: return (v); } } } /* * * create a memry segment with a given pagesize * */ static void * create_memory(size_t size, size_t pagesize) { caddr_t p; p = mmap((void *)pagesize, size, PROT_WRITE|PROT_READ, MAP_ALIGN|MAP_PRIVATE|MAP_ANON, -1, 0); if (p == MAP_FAILED) { char code; size_t out; format_num(pagesize, &out, &code); fprintf(stderr, "mmap(%lu%c,", out, code); format_num(size, &out, &code); fprintf(stderr, " %lu%c, ...)", out, code); perror("failed"); exit(1); } return (p); } int main (int argc, char **argv) { hrtime_t start, end, total = 0; unsigned int i; unsigned int iterations = 1; size_t pagesize = getpagesize(); size_t size = 1024; longlong_t j; longlong_t k; char *table; volatile int value; int c; int verbose = 0; int delta = 1; int normalize = 0; size_t count; size_t count_requested = 0; double normalized; char filename[256]; while ((c = getopt( argc, argv, "Nhvc:d:f:s:n:")) != EOF) { switch (c) { case 'n': iterations = parse_num(optarg); break; case 's': size = parse_num(optarg); break; case 'v': verbose = 1; break; case 'd': delta = atoi(optarg); break; case 'c': count_requested = parse_num(optarg); break; case 'f': strcpy(filename, optarg); break; case 'N': normalize = 1; break; case 'h': default: usage(basename(argv[0])); break; } } if (ABS(delta) >= size) { fprintf(stderr, "delta %llu is larger than size %llu\n", ABS(delta), size); exit(1); } count = count_requested ? count_requested : size; if (verbose) printf("Creating table of %llu bytes\n", size); table = create_memory(size, pagesize); for (i = 0; i < iterations; i++) { int n; int offset = 0; int fd = -1; if ((fd = open(filename, O_RDONLY)) < 0) { perror("open"); exit(1); } k = size - 1; start = gethrtime(); while ((n = read(fd, &table[offset], KB(8))) >0) { offset += n; offset %= size; } end = gethrtime(); total += (end - start); normalized = (double)(end - start) / count; if (verbose) { printf("total time: %llu, normalized time: %g\n", end - start, normalized); } else if (normalize) { printf("%g\n", (double)(end - start) / count); } close(fd); } printf("%llu\n", total); exit(0); }