Last active
January 29, 2019 13:51
-
-
Save hadrianw/ad07a76f338f09565703ae6ea35993c8 to your computer and use it in GitHub Desktop.
Test Linux fork/vfork+exec(dynamic/static binary) performance. Dependecies: gcc, musl-dev, musl-tools (musl-gcc). Usage: $ chmod +x forktest.c $ ./forktest.c 100000
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if 0 | |
set -e; | |
cflags="-O2 -Wall -Wextra -pedantic -std=c99" | |
[ "$0" -nt "$0-regular.bin" ] && | |
gcc $cflags -lpthread "$0" -o "$0-regular.bin" | |
[ "$0" -nt "$0-static.bin" ] && { | |
mkdir -p musl-inc | |
for i in linux x86_64-linux-gnu/asm asm-generic; do | |
ln -fs "/usr/include/$i" musl-inc/ | |
done | |
musl-gcc $cflags -Imusl-inc -static "$0" -o "$0-static.bin" | |
} | |
echo regular | |
"$0-regular.bin" "$@" | |
echo static | |
"$0-static.bin" "$@" | |
exit 0 | |
#endif | |
#define _DEFAULT_SOURCE | |
#include <errno.h> | |
#include <pthread.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <sys/wait.h> | |
#include <time.h> | |
#include <unistd.h> | |
static void | |
using(void) | |
{ | |
fputs("using: ./forktest N \t\t(N > 0)\n", stderr); | |
exit(-1); | |
} | |
static void | |
chld(int sig) | |
{ | |
(void)sig; | |
while(wait(NULL) != -1 || errno != ECHILD) { | |
} | |
} | |
static void* | |
waiter(void *arg) | |
{ | |
(void)arg; | |
signal(SIGCHLD, chld); | |
while(1) { | |
usleep(500 * 1000); | |
} | |
return NULL; | |
} | |
static long | |
ts2ms(struct timespec *tp) | |
{ | |
return tp->tv_sec * 1000 + tp->tv_nsec / 1000 / 1000; | |
} | |
int | |
main(int argc, char *argv[]) | |
{ | |
int n; | |
pthread_t tid; | |
char *args[] = {"none", NULL}; | |
struct timespec tstart; | |
struct timespec tstop; | |
long t; | |
if(!strcmp(argv[0], "none")) { | |
return 0; | |
} | |
if(argc < 2) { | |
using(); | |
} | |
n = atoi(argv[1]); | |
if(n <= 0) { | |
using(); | |
} | |
pthread_create(&tid, NULL, waiter, NULL); | |
clock_gettime(CLOCK_MONOTONIC, &tstart); | |
for(int i = 0; i < n; i++) { | |
pid_t pid = fork(); | |
if(pid == 0) { | |
execv(argv[0], args); | |
} | |
} | |
clock_gettime(CLOCK_MONOTONIC, &tstop); | |
t = ts2ms(&tstop) - ts2ms(&tstart); | |
printf("fork %ld ms / %d = %ld µs, %ld per sec\n", | |
t, n, t*1000 / n, t > 0 ? 1000 * n / t : -1 | |
); | |
clock_gettime(CLOCK_MONOTONIC, &tstart); | |
for(int i = 0; i < n; i++) { | |
pid_t pid = vfork(); | |
if(pid == 0) { | |
execv(argv[0], args); | |
} | |
} | |
clock_gettime(CLOCK_MONOTONIC, &tstop); | |
t = ts2ms(&tstop) - ts2ms(&tstart); | |
printf("vfork %ld ms / %d = %ld µs, %ld per sec\n", | |
t, n, t*1000 / n, t > 0 ? 1000 * n / t : -1 | |
); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Dependecies: gcc, musl-dev, musl-tools (musl-gcc).
$ sudo apt install musl-dev musl-tools
Usage:
$ chmod +x forktest.c
$ ./forktest.c 100000
Intel Core i5 6600k:
regular
fork 13179 ms / 100000 = 131 µs, 7587 per sec
vfork 14423 ms / 100000 = 144 µs, 6933 per sec
static
fork 3173 ms / 100000 = 31 µs, 31515 per sec
vfork 3833 ms / 100000 = 38 µs, 26089 per sec
Intel Celeron N3060 under ChromeOS Crostini:
regular
fork 176227 ms / 100000 = 1762 µs, 567 per sec
vfork 166300 ms / 100000 = 1663 µs, 601 per sec
static
fork 50729 ms / 100000 = 507 µs, 1971 per sec
vfork 45310 ms / 100000 = 453 µs, 2207 per sec