#include #include #include #include #include #include #include #include #include #define N 100000 static void print_dur(struct timespec *start, struct timespec *end, int nlog, const char *sys) { end->tv_sec -= start->tv_sec; if ((end->tv_nsec -= start->tv_nsec) < 0) { end->tv_sec -= 1; end->tv_nsec += 1000000000L; } printf("%-10s 1<<%i %li.%09li\n", sys, nlog, end->tv_sec, end->tv_nsec); fflush(stdout); } int main(void) { char *buf = malloc(1 << 25); int i, nlog; int rw[2]; size_t n, p; ssize_t r; struct timespec start, end; struct iovec iov; memset(buf, 0, 1 << 25); for (nlog = 0; nlog <= 25; nlog++) { n = 1 << nlog; socketpair(PF_UNIX, SOCK_STREAM, 0, rw); if (!fork()) { close(rw[1]); while (read(rw[0], buf, n) > 0); exit(0); } else { close(rw[0]); clock_gettime(CLOCK_MONOTONIC, &start); for (i = 0; i < N; i++) for (p = 0; p < n; p += (size_t)r) if ((r = write(rw[1], buf + p, n - p)) < 0) return perror("write "), 1; close(rw[1]); wait(NULL); clock_gettime(CLOCK_MONOTONIC, &end); print_dur(&start, &end, nlog, "socketpair"); } pipe(rw); #if 0 if (fcntl(*rw, F_SETPIPE_SZ, 1 << 20) < 0) return perror("fcntl F_SETPIPE_SZ"), 1; #endif if (!fork()) { close(rw[1]); while (read(rw[0], buf, n) > 0); exit(0); } else { close(rw[0]); clock_gettime(CLOCK_MONOTONIC, &start); for (i = 0; i < N; i++) for (p = 0; p < n; p += (size_t)r) if ((r = write(rw[1], buf + p, n - p)) < 0) return perror("write "), 1; close(rw[1]); wait(NULL); clock_gettime(CLOCK_MONOTONIC, &end); print_dur(&start, &end, nlog, "pipe"); } pipe(rw); #if 0 if (fcntl(*rw, F_SETPIPE_SZ, 1 << 20) < 0) return perror("fcntl F_SETPIPE_SZ"), 1; #endif if (!fork()) { close(rw[1]); while (read(rw[0], buf, n) > 0); exit(0); } else { close(rw[0]); clock_gettime(CLOCK_MONOTONIC, &start); for (i = 0; i < N; i++) { iov.iov_base = buf; iov.iov_len = n; for (p = 0; p < n; p += (size_t)r) { r = vmsplice(rw[1], &iov, 1, 0); if (r < 0) return perror("vmsplice "), 1; iov.iov_base += r; iov.iov_len -= (size_t)r; } } close(rw[1]); wait(NULL); clock_gettime(CLOCK_MONOTONIC, &end); print_dur(&start, &end, nlog, "vmsplice"); } } return 0; }