My just-shovel-data-through-for-X-amount-of-time test
From: David Howells
Date: Fri Sep 13 2019 - 09:06:43 EST
/*
* Benchmark a pipe by seeing how many 511-byte writes can be stuffed through
* it in a certain amount of time. Compile with -lm.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <math.h>
#include <sys/wait.h>
#include <sys/mman.h>
static char buf1[4096] __attribute__((aligned(4096)));
static char buf2[4096] __attribute__((aligned(4096)));
static unsigned long long *results;
static volatile int stop;
void sigalrm(int sig)
{
stop = 1;
}
static __attribute__((noreturn))
void producer(int fd, int i)
{
unsigned long long l = 0;
ssize_t n;
signal(SIGALRM, sigalrm);
alarm(1);
while (!stop) {
n = write(fd, buf1, 511);
if (n == -1) {
perror("read");
exit(1);
}
l += n;
}
results[i] = l;
exit(0);
}
static __attribute__((noreturn))
void consumer(int fd)
{
unsigned long long l = 0;
ssize_t n;
for (;;) {
n = read(fd, buf2, 4096);
if (n == 0)
break;
if (n == -1) {
perror("read");
exit(1);
}
l += n;
}
exit(0);
}
unsigned long long stddev(const unsigned long long *vals, int nvals)
{
double sum = 0.0, mean, sd = 0.0;
int i;
for (i = 0; i < nvals; i++)
sum += vals[i];
mean = sum / nvals;
for (i = 0; i < nvals; i++)
sd += pow(vals[i] - mean, 2);
return sqrt(sd / 10);
}
int main()
{
unsigned long long t = 0;
int ex = 0, i;
results = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (results == MAP_FAILED) {
perror("mmap");
exit(1);
}
for (i = 0; i < 16 && ex == 0; i++) {
pid_t prod, con;
int pfd[2], wt;
if (pipe2(pfd, 0) < 0) {
perror("pipe");
exit(1);
}
con = fork();
switch (con) {
case -1:
perror("fork/c");
exit(1);
case 0:
close(pfd[1]);
consumer(pfd[0]);
default:
break;
}
prod = fork();
switch (prod) {
case -1:
perror("fork/p");
exit(1);
case 0:
close(pfd[0]);
producer(pfd[1], i);
default:
break;
}
close(pfd[0]);
close(pfd[1]);
for (;;) {
errno = 0;
wait(&wt);
if (errno == ECHILD)
break;
if (!WIFEXITED(wt) || WEXITSTATUS(wt) != 0)
ex = 1;
}
printf("WR[%02u]: %12llu\n", i, results[i]);
t += results[i];
}
printf("total : %12llu\n", t);
printf("avg : %12llu\n", t / i);
printf("stddev: %12llu\n", stddev(results, i));
exit(ex);
}