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; }