ref: a1c8da91f18c8bd3cdc7ce36c70538969e0c5602
dir: /spawn.c/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
#include <spawn.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "bench.h"
#define DirtySz 1024*1024*1024
void *junk;
#ifdef NOPE
void
setupfork(void)
{
if(DirtySz != 0){
if((junk = malloc(DirtySz)) == nil)
sysfatal("malloc: %r");
memset(junk, 42, DirtySz);
}
}
#endif
typedef struct Args Args;
struct Args
{
void (*fn)(int);
int n;
};
static void *
worker(void *arg)
{
Args *a = arg;
a->fn(a->n);
return NULL;
}
void
doit(void (*fn)(int), int n)
{
pthread_t t[256];
Args a[256];
int i;
assert(NPROC <= 256);
for(i = 0; i < NPROC; i++){
a[i].fn = fn;
a[i].n = n/NPROC;
pthread_create(&t[i], NULL, worker, &a[i]);
}
for(i = 0; i < NPROC; i++)
pthread_join(t[i], NULL);
}
void
benchfork(int N)
{
int i;
fflush(stdout); // clear the buffer.
for(i = 0; i < N; i++){
switch(fork()){
case -1:
fprintf(stderr, "fork failed\n");
exit(1);
case 0:
exit(0);
default:
wait(NULL);
}
}
}
static void *
empty_thread(void *arg)
{
return NULL;
}
void
benchpthread(int N)
{
int i;
pthread_t thread;
for(i = 0; i < N; i++){
if(pthread_create(&thread, NULL, empty_thread, NULL) != 0) {
fprintf(stderr, "pthread_create failed\n");
exit(1);
}
pthread_join(thread, NULL);
}
}
void
benchexec(int N)
{
int i;
for(i = 0; i < N; i++){
switch(fork()){
case -1:
abort();
case 0:
execl("./nop", "nop", NULL);
fprintf(stderr, "exec: %s\n", strerror(errno));
abort();
default:
wait(NULL);
}
}
}
void
benchexecm(int N)
{
int i;
pid_t pid;
char *argv[] = {"nop", NULL};
for(i = 0; i < N; i++){
if(posix_spawn(&pid, "./nop", NULL, NULL, argv, NULL) != 0) {
fprintf(stderr, "posix_spawn failed\n");
abort();
}
waitpid(pid, NULL, 0);
}
}
void
benchfork1(B *b)
{
benchfork(b->N);
}
void
benchforkN(B *b)
{
doit(benchfork, b->N);
}
void
benchrforkm1(B *b)
{
benchpthread(b->N);
}
void
benchrforkmN(B *b)
{
doit(benchpthread, b->N);
}
void
benchexec1(B *b)
{
benchexec(b->N);
}
void
benchexecN(B *b)
{
doit(benchexec, b->N);
}
void
benchexecm1(B *b)
{
benchexecm(b->N);
}
void
benchexecmN(B *b)
{
doit(benchexecm, b->N);
}
int
main(int argc, char **argv)
{
benchinit(argc, argv);
printf("== fork/exec (single spawner) ==\n");
BM(benchfork1);
BM(benchrforkm1);
BM(benchexec1);
BM(benchexecm1);
printf("== fork/exec (%d spawners) ==\n", NPROC);
BM(benchforkN);
BM(benchrforkmN);
BM(benchexecN);
BM(benchexecmN);
return 0;
}