Listing 1: Creates a large linked list and destroys it

/*
 * $Id: listing1.c,v 1.4 2002/06/04 12:53:04 gene Exp gene $
 * Performance comparison
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <gc.h>

struct node
{
  struct node *next;
  int dummy_payload;
};

static const double loop_seconds = 17.0;
static const int list_length = (2 * 1024 * 1024) / sizeof (struct node);

/* Make a new list of 'length' nodes.  'alloc' should be
 * &malloc or &GC_malloc. */
static struct node *
MakeList (int length, void *(*alloc) (size_t))
{
  struct node *lst = NULL, *tmp;

  while (length-- > 0) {
    tmp = (struct node *) (*alloc) (sizeof *tmp);
    tmp->next = lst;
    lst = tmp;
  }
  return lst;
}

/* Explicitly free the nodes in the list. */
static void
FreeList (struct node *lst)
{
  while (lst != NULL) {
    struct node *tmp = lst->next;
    free (lst);
    lst = tmp;
  }
}

/* Pretend to free the list, but do nothing.  Rely on garbage
 * collection to free the list. */
static void
IgnoreList (struct node *lst)
{
}

static unsigned long
Loop (void *(*alloc) (size_t), void (*free_list) (struct node *))
{
  unsigned long count = 0;
  time_t start, now;

  time (&start);
  do {
    ++count;
    (*free_list) (MakeList (list_length, alloc));
    time (&now);
  } while (difftime (now, start) < loop_seconds);
  return count;
}

static double
Print (char name[], void *(*alloc) (size_t),
       void (*free_list) (struct node *), double base)
{
  time_t start, end;
  unsigned long count;
  double duration, rate, relative;

  time (&start);
  count = Loop (alloc, free_list);
  time (&end);
  duration = difftime (end, start);
  rate = count / duration;
  relative = base == 0.0 ? 1.0 : rate / base;
  printf ("%10s  %9lu  %9.2e  %9.2e  %9.2f\n", name, count, duration, rate, relative);
  return rate;
}

int
main ()
{
  double malloc_rate;

  printf ("%10s  %9s  %9s  %9s  %9s\n", "name", "count", "duration", 
          "rate", "relative");
  malloc_rate = Print ("malloc", &malloc, &FreeList, 0.0);
  Print ("Boehm", &GC_malloc, &IgnoreList, malloc_rate);
  return 0;
}