shithub: sysbench

ref: a1c8da91f18c8bd3cdc7ce36c70538969e0c5602
dir: /spawn.c/

View raw version
#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;
}