changeset 4200:8fca3338b9ad draft

eloop-bench: fix reading the last write The last write was never read from the pipe in the run, so many runs filled the kernel buffer causing an error which was not seen because the pipe was blocking. Set the pipes to non blocking and improve the exit conditions, also ensuring the bench returns any error back. While here add more timings and run critera. Thanks to Christos Zoulas for helping.
author Roy Marples <roy@marples.name>
date Fri, 05 Jan 2018 17:29:27 +0000
parents 4ba50d96e94d
children 965264ca96bc
files tests/eloop-bench/eloop-bench.c
diffstat 1 files changed, 51 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/tests/eloop-bench/eloop-bench.c	Tue Jan 02 16:36:04 2018 +0000
+++ b/tests/eloop-bench/eloop-bench.c	Fri Jan 05 17:29:27 2018 +0000
@@ -26,7 +26,9 @@
  */
 
 #include <sys/resource.h>
+
 #include <err.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
@@ -59,38 +61,37 @@
 read_cb(void *arg)
 {
 	struct pipe *p = arg;
-	unsigned char c;
-	ssize_t l;
+	unsigned char buf[1];
 
-	l = read(p->fd[0], &c, sizeof(c));
-	if (l == -1)
+	if (read(p->fd[0], buf, 1) != 1) {
+		warn("%s: read", __func__);
 		bad++;
-	else
-		good += (size_t)l;
-	if (writes) {
-		p = (struct pipe *)arg;
-		l = write(p->fd[1], "e", 1);
-		if (l != 1)
+	} else
+		good++;
+
+	if (writes != 0) {
+		writes--;
+		if (write(p->fd[1], "e", 1) != 1) {
+			warn("%s: write", __func__);
 			bad++;
-		else {
-			writes -= (size_t)l;
-			fired += (size_t)l;
-		}
+		} else
+			fired++;
 	}
 
-	if (writes == 0) {
-		if (good == fired)
-			eloop_exit(e, EXIT_SUCCESS);
+	if (writes == 0 && fired == good) {
+		//printf("fired %zu, good %zu, bad %zu\n", fired, good, bad);
+		eloop_exit(e, good == fired && bad == 0 ?
+		    EXIT_SUCCESS : EXIT_FAILURE);
 	}
 }
 
-static struct timespec *
-runone(void)
+static int
+runone(struct timespec *t)
 {
 	size_t i;
 	struct pipe *p;
-	static struct timespec _ts;
 	struct timespec ts, te;
+	int result;
 
 	writes = nwrites;
 	fired = good = 0;
@@ -98,28 +99,27 @@
 	for (i = 0, p = pipes; i < nactive; i++, p++) {
 		if (write(p->fd[1], "e", 1) != 1)
 			err(EXIT_FAILURE, "send");
+		writes--;
+		fired++;
 	}
 
 	if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
 		err(EXIT_FAILURE, "clock_gettime");
-	(void) eloop_start(e, NULL);
+	result = eloop_start(e, NULL);
 	if (clock_gettime(CLOCK_MONOTONIC, &te) == -1)
 		err(EXIT_FAILURE, "clock_gettime");
 
-	timespecsub(&te, &ts, &_ts);
-	return &_ts;
+	timespecsub(&te, &ts, t);
+	return result;
 }
 
 int
 main(int argc, char **argv)
 {
-	int c;
+	int c, result, exit_code;
 	size_t i, nruns = 25;
 	struct pipe *p;
-	struct timespec *ts;
-
-	if ((e = eloop_new()) == NULL)
-		err(EXIT_FAILURE, "eloop_init");
+	struct timespec ts, te, t;
 
 	while ((c = getopt(argc, argv, "a:n:r:w:")) != -1) {
 		switch (c) {
@@ -140,6 +140,12 @@
 		}
 	}
 
+	if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
+		err(EXIT_FAILURE, "clock_gettime");
+
+	if ((e = eloop_new()) == NULL)
+		err(EXIT_FAILURE, "eloop_init");
+
 	if (nactive > npipes)
 		nactive = npipes;
 
@@ -148,19 +154,31 @@
 		err(EXIT_FAILURE, "malloc");
 
 	for (i = 0, p = pipes; i < npipes; i++, p++) {
-		if (pipe(p->fd) == -1)
+		if (pipe2(p->fd, O_CLOEXEC | O_NONBLOCK) == -1)
 			err(EXIT_FAILURE, "pipe");
 		if (eloop_event_add(e, p->fd[0], read_cb, p) == -1)
 			err(EXIT_FAILURE, "eloop_event_add");
 	}
 
+	printf("active = %zu, pipes = %zu, runs = %zu, writes = %zu\n",
+	    nactive, npipes, nruns, nwrites);
+
+	exit_code = EXIT_SUCCESS;
 	for (i = 0; i < nruns; i++) {
-		if ((ts = runone()) == NULL)
-			err(EXIT_FAILURE, "runone");
-		printf("%lld.%.9ld\n", (long long)ts->tv_sec, ts->tv_nsec);
+		result = runone(&t);
+		if (result != EXIT_SUCCESS)
+			exit_code = result;
+		printf("run %zu took %lld.%.9ld seconds, result %d\n",
+		    i + 1, (long long)t.tv_sec, t.tv_nsec, result);
 	}
 
 	eloop_free(e);
 	free(pipes);
-	exit(0);
+
+	if (clock_gettime(CLOCK_MONOTONIC, &te) == -1)
+		err(EXIT_FAILURE, "clock_gettime");
+	timespecsub(&te, &ts, &t);
+	printf("total %lld.%.9ld seconds, result %d\n",
+	    (long long)t.tv_sec, t.tv_nsec, exit_code);
+	exit(exit_code);
 }