11 #include <sys/types.h>
15 #include <netinet/in.h>
16 #include <arpa/inet.h>
22 static int nr_clients = 8;
23 static int net_port = 8888;
24 static int client_loops = 10;
26 static int write_to_null;
28 static int splice_size = SPLICE_SIZE;
29 static char *filename = "splice-file";
33 static int usage(char *name)
35 fprintf(stderr, "Usage %s [options] [filename]:\n", name);
36 fprintf(stderr, "\t[-n] (number of clients]\n");
37 fprintf(stderr, "\t[-p] (port number)\n");
38 fprintf(stderr, "\t[-l] (number of loops)\n");
39 fprintf(stderr, "\t[-z] (write to /dev/null)\n");
40 fprintf(stderr, "\t[-s] (use 1 file for all)\n");
41 fprintf(stderr, "\t[-a] (set CPU affinity)\n");
42 fprintf(stderr, "\t[-b] (splice chunk size)\n");
46 static int parse_options(int argc, char *argv[])
50 while ((c = getopt(argc, argv, "n:p:l:azsb:")) != -1) {
53 nr_clients = atoi(optarg);
57 net_port = atoi(optarg);
61 client_loops = atoi(optarg);
77 splice_size = atoi(optarg);
88 int bind_to_cpu(int index)
94 if (!bind_cpu || nr_cpus == 1)
97 cpu = index % nr_cpus;
100 CPU_SET((cpu), &cpu_mask);
103 if (sched_setaffinity(pid, sizeof(cpu_mask), &cpu_mask) == -1)
104 return error("set affinity");
109 int accept_loop(int listen_sk)
111 unsigned long received;
112 struct sockaddr addr;
113 unsigned int len = sizeof(addr);
117 sk = accept(listen_sk, &addr, &len);
119 return error("accept");
124 int ret = recv(sk, NULL, 128*1024*1024, MSG_TRUNC);
131 if (errno == EAGAIN || errno == EINTR)
140 int server(int offset)
142 struct sockaddr addr;
143 struct sockaddr_in saddr_in;
150 sk = socket(PF_INET, SOCK_STREAM, 0);
152 return error("socket");
154 saddr_in.sin_addr.s_addr = htonl(INADDR_ANY);
155 saddr_in.sin_port = htons(net_port + offset);
157 if (bind(sk, (struct sockaddr*)&saddr_in, sizeof(saddr_in)) < 0)
158 return error("bind");
160 if (listen(sk, 1) < 0)
161 return error("listen");
164 if (getsockname(sk, &addr, &len) < 0)
165 return error("getsockname");
167 return accept_loop(sk);
170 static unsigned long mtime_since(struct timeval *s, struct timeval *e)
174 sec = e->tv_sec - s->tv_sec;
175 usec = e->tv_usec - s->tv_usec;
176 if (sec > 0 && usec < 0) {
181 sec *= (double) 1000;
182 usec /= (double) 1000;
187 static unsigned long mtime_since_now(struct timeval *s)
191 gettimeofday(&t, NULL);
192 return mtime_since(s, &t);
195 int client_loop(int out_fd, int fd, int *pfd, int offset)
197 struct timeval start;
198 unsigned long long size;
201 int loops = client_loops;
204 if (fstat(fd, &sb) < 0)
205 return error("fstat");
207 gettimeofday(&start, NULL);
214 int ret = splice(fd, &off, pfd[1], NULL, min(size, (unsigned long long) splice_size), 0);
217 return error("splice-in");
221 int flags = size ? SPLICE_F_MORE : 0;
222 int written = splice(pfd[0], NULL, out_fd, NULL, ret, flags);
225 return error("splice-out");
234 size = sb.st_size >> 10;
235 size *= client_loops;
236 msecs = mtime_since_now(&start);
237 fprintf(stdout, "Client%d: %Lu MiB/sec\n", offset, size / msecs);
241 static int client_open_net(int offset)
243 int sk = socket(PF_INET, SOCK_STREAM, 0);
244 struct sockaddr_in s_to;
247 hp = gethostbyname("localhost");
249 return error("gethostbyname");
251 bzero((char *) &s_to, sizeof (s_to));
252 bcopy((char *) hp->h_addr, (char *) &(s_to.sin_addr), hp->h_length);
253 s_to.sin_family = hp->h_addrtype;
254 s_to.sin_port = htons(net_port + offset);
256 if (connect(sk, (struct sockaddr *)&s_to, sizeof(s_to)) < 0)
257 return error("connect");
262 int client(int offset)
272 out_fd = client_open_net(offset);
274 out_fd = open("/dev/null", O_WRONLY);
277 return error("socket");
279 sprintf(fname, "%s%d", filename, same_file ? 0 : offset);
280 file_fd = open(filename, O_RDONLY);
282 return error("open");
285 return error("pipe");
287 return client_loop(out_fd, file_fd, pfd, offset);
290 int main(int argc, char *argv[])
292 pid_t *spids, *cpids;
295 index = parse_options(argc, argv);
297 return usage(argv[0]);
300 filename = argv[index];
302 spids = malloc(nr_clients * sizeof(pid_t));
303 cpids = malloc(nr_clients * sizeof(pid_t));
304 memset(spids, 0, nr_clients * sizeof(pid_t));
305 memset(cpids, 0, nr_clients * sizeof(pid_t));
307 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
309 return error("_SC_NPROCESSORS_ONLN");
311 fprintf(stdout,"Processors: %d\n", nr_cpus);
316 if (!write_to_null) {
317 for (i = 0; i < nr_clients; i++) {
328 sleep(1); /* should have servers started now */
334 for (i = 0; i < nr_clients; i++) {
347 * wait for clients to exit
349 fprintf(stdout, "Waiting for clients\n");
350 for (i = 0; i < nr_clients; i++) {
352 waitpid(cpids[i], NULL, 0);
360 for (i = 0; i < nr_clients; i++) {
362 kill(spids[i], SIGKILL);
363 waitpid(spids[i], NULL, 0);