Skip to content

Instantly share code, notes, and snippets.

@hadrianw
Last active January 29, 2019 13:51
Show Gist options
  • Save hadrianw/ad07a76f338f09565703ae6ea35993c8 to your computer and use it in GitHub Desktop.
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
#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;
}
@hadrianw
Copy link
Author

hadrianw commented Jan 28, 2019

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment