summaryrefslogtreecommitdiffstats
path: root/bench.c
blob: 8e0f09102b4c212f2155f8760ce4b0b9030a7a59 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#define _GNU_SOURCE
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>


#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 <socket>"), 1;
			close(rw[1]);
			wait(NULL);
			clock_gettime(CLOCK_MONOTONIC, &end);
			print_dur(&start, &end, nlog, "socketpair");
		}

		pipe(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 <pipe>"), 1;
			close(rw[1]);
			wait(NULL);
			clock_gettime(CLOCK_MONOTONIC, &end);
			print_dur(&start, &end, nlog, "pipe");
		}

		pipe(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++) {
				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 <pipe>"), 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;
}