/*
 * Copyright (c) 2002-2005 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: b-lists.c,v 1.10 2005/04/14 17:14:02 ca Exp $")

#include "sm/assert.h"
#include "sm/magic.h"
#include "sm/heap.h"
#include "sm/test.h"
#include "sm/queue.h"

#include <stdio.h>

#include <sys/time.h>
#define toseconds(x, y)	(x.tv_sec - y.tv_sec)

static int Verbose = 0;
struct timeval t1, t2;

#define GT(ti) do {	\
	if (gettimeofday((ti), NULL) < 0)	\
		perror("gettimeofday");	\
	} while (0)
#define START() GT(&t1)
#define END() GT(&t2)
#define DONE() do { if (Verbose > 0) \
	printf("function time: %ld seconds\n", toseconds(t2, t1));	\
	} while (0)

#define ELEMS	1024
#define ITER	100

struct tq_entry
{
	int			item;
	TAILQ_ENTRY(tq_entry)	entries;
};

TAILQ_HEAD(tq, tq_entry) tq_head;

typedef struct tq_entry tq_entry_T;
typedef struct tq tq_T;

static void
test_tq(int iter)
{
	int i, j, old, count;
	tq_T head;
	tq_entry_T *tqe, *np;

	TAILQ_INIT(&head);
	SM_TEST(TAILQ_EMPTY(&head));
	tqe = (tq_entry_T *) sm_malloc(ELEMS * sizeof(*tqe));
	for (i = 0; i < ELEMS; i++)
		tqe[i].item = i;

	START();
	for (j = 0; j < iter; j++)
	{
		TAILQ_INIT(&head);
		for (i = 0; i < ELEMS; i++)
		{
			TAILQ_INSERT_TAIL(&head, &(tqe[i]), entries);
		}
		old = -1;
		count = 0;
		TAILQ_FOREACH(np, &head, entries)
		{
			SM_TEST(old < np->item);
			old = np->item;
			++count;
		}
	}
	END();
	DONE();
	sm_free(tqe);
}

struct sl_entry
{
	int			item;
	SLIST_ENTRY(sl_entry)	entries;
};

SLIST_HEAD(sl, sl_entry) sl_head;

typedef struct sl_entry sl_entry_T;
typedef struct sl sl_T;

static void
test_sl(int iter)
{
	int i, j, old, count;
	sl_T head;
	sl_entry_T *sle, *np;

	SLIST_INIT(&head);
	SM_TEST(SLIST_EMPTY(&head));
	sle = (sl_entry_T *) sm_malloc(ELEMS * sizeof(*sle));
	for (i = 0; i < ELEMS; i++)
		sle[i].item = i;

	START();
	for (j = 0; j < iter; j++)
	{
		SLIST_INIT(&head);
		for (i = 0; i < ELEMS; i++)
		{
			/* tail doesn't work... */
			SLIST_INSERT_HEAD(&head, &(sle[i]), entries);
		}
		old = ELEMS + 1;
		count = 0;
		SLIST_FOREACH(np, &head, entries)
		{
			SM_TEST(old > np->item);
			old = np->item;
			++count;
		}
	}
	END();
	DONE();
	sm_free(sle);
}

struct li_entry
{
	int			item;
	LIST_ENTRY(li_entry)	entries;
};

LIST_HEAD(li, li_entry) li_head;

typedef struct li_entry li_entry_T;
typedef struct li li_T;

static void
test_li(int iter)
{
	int i, j, old, count;
	li_T head;
	li_entry_T *lie, *np;

	LIST_INIT(&head);
	SM_TEST(LIST_EMPTY(&head));
	lie = (li_entry_T *) sm_malloc(ELEMS * sizeof(*lie));
	for (i = 0; i < ELEMS; i++)
		lie[i].item = i;

	START();
	for (j = 0; j < iter; j++)
	{
		LIST_INIT(&head);
		for (i = 0; i < ELEMS; i++)
		{
			/* tail doesn't work... */
			LIST_INSERT_HEAD(&head, &(lie[i]), entries);
		}
		old = ELEMS + 1;
		count = 0;
		LIST_FOREACH(np, &head, entries)
		{
			SM_TEST(old > np->item);
			old = np->item;
			++count;
		}
	}
	END();
	DONE();
	sm_free(lie);
}

struct cq_entry
{
	int			item;
	CIRCLEQ_ENTRY(cq_entry)	entries;
};

CIRCLEQ_HEAD(cq, cq_entry) cq_head;

typedef struct cq_entry cq_entry_T;
typedef struct cq cq_T;

static void
test_cq(int iter)
{
	int i, j, old, count;
	cq_T head;
	cq_entry_T *cqe, *np;

	CIRCLEQ_INIT(&head);
	SM_TEST(CIRCLEQ_EMPTY(&head));
	cqe = (cq_entry_T *) sm_malloc(ELEMS * sizeof(*cqe));
	for (i = 0; i < ELEMS; i++)
		cqe[i].item = i;

	START();
	for (j = 0; j < iter; j++)
	{
		CIRCLEQ_INIT(&head);
		for (i = 0; i < ELEMS; i++)
		{
			CIRCLEQ_INSERT_TAIL(&head, &(cqe[i]), entries);
		}
		old = -1;
		count = 0;
		CIRCLEQ_FOREACH(np, &head, entries)
		{
			SM_TEST(old < np->item);
			old = np->item;
			++count;
		}
	}
	END();
	DONE();
	sm_free(cqe);
}


struct sq_entry
{
	int			item;
	SIMPLEQ_ENTRY(sq_entry)	entries;
};

SIMPLEQ_HEAD(sq, sq_entry) sq_head;

typedef struct sq_entry sq_entry_T;
typedef struct sq sq_T;

static void
test_sq(int iter)
{
	int i, j, old, count;
	sq_T head;
	sq_entry_T *sqe, *np;

	SIMPLEQ_INIT(&head);
	SM_TEST(SIMPLEQ_EMPTY(&head));
	sqe = (sq_entry_T *) sm_malloc(ELEMS * sizeof(*sqe));
	for (i = 0; i < ELEMS; i++)
		sqe[i].item = i;

	START();
	for (j = 0; j < iter; j++)
	{
		SIMPLEQ_INIT(&head);
		for (i = 0; i < ELEMS; i++)
		{
			SIMPLEQ_INSERT_TAIL(&head, &(sqe[i]), entries);
		}
		old = -1;
		count = 0;
		SIMPLEQ_FOREACH(np, &head, entries)
		{
			SM_TEST(old < np->item);
			old = np->item;
			++count;
		}
	}
	END();
	DONE();
	sm_free(sqe);
}


int
main(int argc, char *argv[])
{
	int c, iter;

	iter = ITER;
	while ((c = getopt(argc, argv, "l:")) != -1)
	{
		switch (c)
		{
		  case 'l':
			iter = atoi(optarg);
			break;
#if 0
		  default:
			usage(argv[0]);
			return(1);
#endif /* 0 */
		}
	}
	if (iter > ITER)
		Verbose++;
	sm_test_begin(argc, argv, "test lists");
	if (Verbose > 0)
		printf("circleq: ");
	test_cq(iter);
	if (Verbose > 0)
		printf("tailq: ");
	test_tq(iter);
	if (Verbose > 0)
		printf("slist: ");
	test_sl(iter);
	if (Verbose > 0)
		printf("list: ");
	test_li(iter);
	if (Verbose > 0)
		printf("simpleq: ");
	test_sq(iter);
	return sm_test_end();
}

#if 0

cube.dev-lab$ ./b-lists -l 100000
circleq: function time: 18 seconds
tailq: function time: 21 seconds
slist: function time: 8 seconds
list: function time: 21 seconds
simpleq: function time: 16 seconds

zardoc.esmtp.org$ ./b-lists -l 100000
circleq: function time: 9 seconds
tailq: function time: 9 seconds
slist: function time: 7 seconds
list: function time: 9 seconds
simpleq: function time: 7 seconds

sun8.dev-lab$ ./b-lists -l 100000       
circleq: function time: 14 seconds
tailq: function time: 13 seconds
slist: function time: 11 seconds
list: function time: 13 seconds
simpleq: function time: 13 seconds

aix$ $ ./b-lists -l 100000
circleq: function time: 20 seconds
tailq: function time: 19 seconds
slist: function time: 18 seconds
list: function time: 19 seconds
simpleq: function time: 18 seconds

k7.esmtp.org$ ./b-lists -l 100000
circleq: function time: 7 seconds
tailq: function time: 6 seconds
slist: function time: 4 seconds
list: function time: 6 seconds
simpleq: function time: 5 seconds
512000005 of 512000005 tests completed successfully
k7.esmtp.org$ ./b-lists -l 1000000
circleq: function time: 63 seconds
tailq: function time: 61 seconds
slist: function time: 43 seconds
list: function time: 63 seconds
simpleq: function time: 49 seconds
825032709 of 825032709 tests completed successfully


#endif /* 0 */


syntax highlighted by Code2HTML, v. 0.9.1