Skip to content

Instantly share code, notes, and snippets.

@unmanned-player
Created March 12, 2020 08:59
Show Gist options
  • Save unmanned-player/2e0d471d4912f68975ff28988416db71 to your computer and use it in GitHub Desktop.
Save unmanned-player/2e0d471d4912f68975ff28988416db71 to your computer and use it in GitHub Desktop.
A simple test case to benchmark fork() and posix_spawn()
/* Configurations. */
#define WITH_VFORK
// #define TRY_FORK
#define TRY_SPAWN
#define WAIT_PID
#define RUNS 1000
/* Code. */
#ifdef WITH_VFORK
#define _GNU_SOURCE 1
#define _BSD_SOURCE 1
#define _DEFAULT_SOURCE 1
#endif
#ifdef TRY_FORK
#ifdef WITH_VFORK
#define FORK_FMT "vfork,%" PRIu64 ",%u\n"
#else
#define FORK_FMT "nfork,%" PRIu64 ",%u\n"
#endif
#endif
#ifdef TRY_SPAWN
#ifdef WITH_VFORK
#define SPAWN_FMT "vspwan,%" PRIu64 ",%u\n"
#else
#define SPAWN_FMT "nspwan,%" PRIu64 ",%u\n"
#endif
#endif
#include <stdint.h>
#include <stddef.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <spawn.h>
static char exe[] = "/bin/true";
static char *const ARGV[] = { exe, NULL };
#define SEC_US ((uint64_t)(1000 * 1000 * 1000))
#define NSEC_US ((uint64_t)1000)
static inline uint64_t clk_get_ts(void)
{
struct timespec tv;
if (clock_gettime(CLOCK_MONOTONIC, &tv) == 0) {
return ((uint64_t)tv.tv_sec * SEC_US) + ((uint64_t)tv.tv_nsec / NSEC_US);
}
return 0;
}
#ifdef TRY_FORK
static void test_fork(void)
{
pid_t pid;
#ifdef WITH_VFORK
pid = vfork();
#else
pid = fork();
#endif
if (pid == -1) {
perror("fork");
_exit(EXIT_FAILURE);
} else if (pid > 0) {
#ifdef WAIT_PID
int r;
waitpid(pid, &r, 0);
#endif
} else {
execv(ARGV[0], ARGV);
_exit(EXIT_FAILURE);
}
}
#endif
#ifdef TRY_SPAWN
static void test_posix_spawn(void)
{
posix_spawnattr_t attr;
int r;
pid_t pid;
memset(&attr, 0, sizeof(posix_spawnattr_t));
if ((r = posix_spawnattr_init(&attr)) != 0) _exit(EXIT_FAILURE);
#if defined(WITH_VFORK) && defined(POSIX_SPAWN_USEVFORK)
posix_spawnattr_setflags(&attr, POSIX_SPAWN_USEVFORK);
#endif
if ((r = posix_spawn(&pid, ARGV[0], NULL, &attr, ARGV, NULL)) == 0) {
#ifdef WAIT_PID
waitpid(pid, &r, 0);
#endif
}
posix_spawnattr_destroy(&attr);
}
#endif
int main(int argc, char **argv)
{
unsigned i, max;
uint64_t time;
max = (argc > 1)? (unsigned)atoi(argv[1]): RUNS;
#ifdef TRY_FORK
time = clk_get_ts();
for (i = 0; i < max; i++) {
test_fork();
}
time = clk_get_ts() - time;
printf(FORK_FMT, time, max);
#endif
#ifdef TRY_SPAWN
time = clk_get_ts();
for (i = 0; i < max; i++) {
test_posix_spawn();
}
time = clk_get_ts() - time;
printf(SPAWN_FMT, time, max);
#endif
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment