Skip to content

Instantly share code, notes, and snippets.

@nicolasff
Created April 30, 2013 11:30
Show Gist options
  • Save nicolasff/5488142 to your computer and use it in GitHub Desktop.
Save nicolasff/5488142 to your computer and use it in GitHub Desktop.
Testing the performance of swapcontext(3)
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
#include <sys/time.h>
#define COROUTINE_STACK_SIZE (1024 * 1024)
typedef struct {
ucontext_t ctx;
ucontext_t *prev;
char stack[0];
} task_t;
static double
now()
{
struct timeval tv = {0,0};
gettimeofday(&tv, NULL);
return (double)(tv.tv_sec * 1000000 + tv.tv_usec);
}
static void
task_main(task_t *self)
{
while(1) {
/* yield back */
swapcontext(&self->ctx, self->prev);
}
}
static task_t *
make_task(size_t stack_size, ucontext_t *prev)
{
task_t *t;
t = malloc(sizeof(task_t) + stack_size);
/* save previous context for switching back */
t->prev = prev;
/* get current context and allocate a stack for it */
getcontext(&t->ctx);
t->ctx.uc_stack.ss_sp = t->stack;
t->ctx.uc_stack.ss_size = COROUTINE_STACK_SIZE;
t->ctx.uc_stack.ss_flags = 0;
t->ctx.uc_link = 0;
/* point context to task_main for next switch */
makecontext(&t->ctx, (void (*)())task_main, 1, t);
return t;
}
int
main(int argc, char *argv[])
{
long n = 5*1000*1000;
long i;
double start, end;
ucontext_t self;
task_t *t;
(void)argc;
(void)argv;
t = make_task(COROUTINE_STACK_SIZE, &self);
start = now();
for (i = 0; i < n; ++i) {
/* swap to coroutine context */
swapcontext(&self, &t->ctx);
}
end = now();
printf("%ld calls to swapcontext in %0.2f sec (%ld/sec), %0.2f usec each\n",
2*n, (end-start) / (1000000.0f),
(long)((n*2*1000000) / (end-start)),
(end-start) / (n*2));
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment