#include <stdio.h>
#include <sys/time.h>
#include <string.h>

#define TYPEALIGN(ALIGNVAL,LEN)  \
	(((long) (LEN) + ((ALIGNVAL) - 1)) & ~((long) ((ALIGNVAL) - 1)))

#define MemSetLoop(type, start, val, len) \
	do \
	{ \
		type * _start = (type *) (start); \
		type * _stop = (type *) ((char *) _start + (size_t) (len)); \
	\
		while (_start < _stop) \
			*_start++ = 0; \
	} while (0)

#define MAXALIGN	8
#define MAXSIZE		4096
#define LOOP		(1000*1000*64)

static void print_time(const char* msg, int size, const struct timeval *start, const struct timeval *end)
{
	double t;
	t = (end->tv_sec - start->tv_sec) + (end->tv_usec - start->tv_usec) / 1000000.0;
	printf("%s (size=%d) : %f\n", msg, size, t);
}

#define TEST(type, size)	\
	do { \
		int i; \
		gettimeofday(&start, NULL); \
		for(i = 0; i < LOOP; i++) \
		{ \
			MemSetLoop(type, buffer, 0, size); \
		} \
		gettimeofday(&end, NULL); \
		print_time("Loop by " #type, size, &start, &end); \
	} while (0)

#define TESTNATIVE(type, size)	\
	do { \
		int i; \
		gettimeofday(&start, NULL); \
		for(i = 0; i < LOOP; i++) \
		{ \
			memset(buffer, 0, size); \
		} \
		gettimeofday(&end, NULL); \
		print_time("memset by " #type, size, &start, &end); \
	} while (0)

int main()
{
	int j;
	struct timeval start, end;
	char buffer0[MAXSIZE + MAXALIGN];
	char* buffer = (char*) TYPEALIGN(MAXALIGN, buffer0);

	printf("sizeof(int)  = %d\n", sizeof(int));
	printf("sizeof(long) = %d\n", sizeof(long));

	for(j = 0; j < 3; j++)
	{
		TEST(int , 8);
		TESTNATIVE(int , 8);
		TEST(long, 8);
		TEST(int , 16);
		TESTNATIVE(int , 16);
		TEST(long, 16);
		TEST(int , 32);
		TESTNATIVE(int , 32);
		TEST(long, 32);
		TEST(int , 64);
		TESTNATIVE(int , 64);
		TEST(long, 64);
		TEST(int , 128);
		TESTNATIVE(int , 128);
		TEST(long, 128);
		TEST(int , 256);
		TESTNATIVE(int , 256);
		TEST(long, 256);
		TEST(int , 512);
		TESTNATIVE(int , 512);
		TEST(long, 512);
		TEST(int , 1024);
		TESTNATIVE(int , 1024);
		TEST(long, 1024);
		TEST(int , 2048);
		TESTNATIVE(int , 2048);
		TEST(long, 2048);
		TEST(int , 4096);
		TESTNATIVE(int , 4096);
		TEST(long, 4096);
	}
	return 0;
}
