#define COPY_ITERS 10 #define ITERS 1000 #include #include #include #include #include #include #include #include #include #include #include #define SECOND 1000000000 #define MILLISECOND 1000000 #define MICROSECOND 1000 #define MEG (1024 * 1024) #define HALFMEG (MEG >> 1) #define MEG2 (MEG * 2) #define MEG8 (MEG * 8) static const uint64_t PHI = 0x9e3779b97f4a7c15; static uint64_t rand_state; static uint64_t rand_u64() { rand_state += PHI; uint64_t z = rand_state; z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; return z ^ (z >> 31); } typedef struct { struct timespec start, end; } bench; // can fit everything into a float in nanoseconds. double diff(struct timespec start, struct timespec end) { struct timespec temp; if ((end.tv_nsec-start.tv_nsec)<0) { temp.tv_sec = end.tv_sec-start.tv_sec-1; temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; } else { temp.tv_sec = end.tv_sec-start.tv_sec; temp.tv_nsec = end.tv_nsec-start.tv_nsec; } return (double)((1000000000ULL * (uint64_t)temp.tv_sec) + temp.tv_nsec); } void print_stat(double stat) { if (stat >= SECOND) { printf("%7.3f secs", stat / SECOND); return; } if (stat >= MILLISECOND) { printf("%7.3f msec", stat / MILLISECOND); return; } if (stat >= MICROSECOND) { printf("%7.3f usec", stat / MICROSECOND); return; } printf("%7.3f nsec", stat); } void print_bench(char *name, bench b) { double delta = diff(b.start, b.end); printf("%-20s ", name); print_stat(delta); printf(" ( "); print_stat(delta / ITERS); printf(" per iteration )\n"); } bench bench_bs512k_thr1_copy(int in, int out, char * buf) { bench b; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.start); for (int block = 0; block < 2048; block++) { for (int index = 0; index < HALFMEG; ) { ssize_t ret = read(in, &buf[index], HALFMEG - index); if (ret == -1) { fprintf(stderr, "Unexpected read error: %d", errno); exit(1); } else { index += ret; } } for (int index = 0; index < HALFMEG; ) { ssize_t ret = write(out, &buf[index], HALFMEG - index); if (ret == -1) { fprintf(stderr, "Unexpected write error: %d", errno); exit(1); } else { index += ret; } } } int ret = fsync(out); if (ret == -1) { fprintf(stderr, "Unexpected fsync error: %d", errno); exit(3); } clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.end); return b; } bench bench_bs1m_thr1_copy(int in, int out, char * buf) { bench b; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.start); for (int block = 0; block < 1024; block++) { for (int index = 0; index < MEG; ) { ssize_t ret = read(in, &buf[index], MEG - index); if (ret == -1) { fprintf(stderr, "Unexpected read error: %d", errno); exit(1); } else { index += ret; } } for (int index = 0; index < MEG; ) { ssize_t ret = write(out, &buf[index], MEG - index); if (ret == -1) { fprintf(stderr, "Unexpected write error: %d", errno); exit(1); } else { index += ret; } } } int ret = fsync(out); if (ret == -1) { fprintf(stderr, "Unexpected fsync error: %d", errno); exit(3); } clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.end); return b; } bench bench_bs2m_thr1_copy(int in, int out, char * buf) { bench b; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.start); for (int block = 0; block < 512; block++) { for (int index = 0; index < MEG2; ) { ssize_t ret = read(in, &buf[index], MEG2 - index); if (ret == -1) { fprintf(stderr, "Unexpected read error: %d", errno); exit(1); } else { index += ret; } } for (int index = 0; index < MEG; ) { ssize_t ret = write(out, &buf[index], MEG2 - index); if (ret == -1) { fprintf(stderr, "Unexpected write error: %d", errno); exit(1); } else { index += ret; } } } int ret = fsync(out); if (ret == -1) { fprintf(stderr, "Unexpected fsync error: %d", errno); exit(3); } clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.end); return b; } bench bench_bs8m_thr1_copy(int in, int out, char * buf) { bench b; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.start); for (int block = 0; block < 128; block++) { for (int index = 0; index < MEG8; ) { ssize_t ret = read(in, &buf[index], MEG8 - index); if (ret == -1) { fprintf(stderr, "Unexpected read error: %d", errno); exit(1); } else { index += ret; } } for (int index = 0; index < MEG8; ) { ssize_t ret = write(out, &buf[index], MEG8 - index); if (ret == -1) { fprintf(stderr, "Unexpected write error: %d", errno); exit(1); } else { index += ret; } } } int ret = fsync(out); if (ret == -1) { fprintf(stderr, "Unexpected fsync error: %d", errno); exit(3); } clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.end); return b; } static char buf[8 * MEG]; int main(int argc, char **argv) { struct timespec t; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t); int efd = eventfd(0, 0); int in = open("random", O_RDWR); if (in == -1) { fprintf(stderr, "error opening random: %d", errno); return 1; } int out = open(".", O_RDWR | O_TMPFILE); if (out == -1) { fprintf(stderr, "error opening out: %d", errno); return 1; } memset(buf, 0, sizeof(buf)); if (argc < 2 || strchr(argv[1], '5')) { print_bench("copy bs=512K thr=1", bench_bs512k_thr1_copy(in, out, &buf[0])); int ret = lseek(in, 0, SEEK_SET); if (ret == -1) { fprintf(stderr, "Unexpected lseek error: %d", errno); exit(8); } ret = lseek(out, 0, SEEK_SET); if (ret == -1) { fprintf(stderr, "Unexpected lseek error: %d", errno); exit(8); } } if (argc < 2 || strchr(argv[1], '1')) { print_bench("copy bs=1M thr=1", bench_bs1m_thr1_copy(in, out, &buf[0])); int ret = lseek(in, 0, SEEK_SET); if (ret == -1) { fprintf(stderr, "Unexpected lseek error: %d", errno); exit(8); } ret = lseek(out, 0, SEEK_SET); if (ret == -1) { fprintf(stderr, "Unexpected lseek error: %d", errno); exit(8); } } if (argc < 2 || strchr(argv[1], '2')) { print_bench("copy bs=2M thr=1", bench_bs2m_thr1_copy(in, out, &buf[0])); int ret = lseek(in, 0, SEEK_SET); if (ret == -1) { fprintf(stderr, "Unexpected lseek error: %d", errno); exit(8); } ret = lseek(out, 0, SEEK_SET); if (ret == -1) { fprintf(stderr, "Unexpected lseek error: %d", errno); exit(8); } } if (argc < 2 || strchr(argv[1], '8')) { print_bench("copy bs=8M thr=1", bench_bs8m_thr1_copy(in, out, &buf[0])); int ret = lseek(in, 0, SEEK_SET); if (ret == -1) { fprintf(stderr, "Unexpected lseek error: %d", errno); exit(8); } ret = lseek(out, 0, SEEK_SET); if (ret == -1) { fprintf(stderr, "Unexpected lseek error: %d", errno); exit(8); } } /* print_bench("copy bs=1M thr=8", bench_bs1m_thr8_copy(in, out, efd, &buf[0])); */ return 0; }