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

#define BUFSIZE 1024
#define LP_COUNT 1000

unsigned long gettimestamp(void)
{
	unsigned long ts_us = 0;
	struct timespec ts;
	clock_gettime(CLOCK_MONOTONIC, &ts);
	ts_us = ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
	return ts_us;
}

int mem_func(int size)
{
	char *p, *q;
	int i;

	p = malloc(size);
	q = p;
	if (p) {
		for (i=0; i<size; i++) {
			*p++ = i;
		}
	}
	else {
		perror("malloc");
		return -1;
	}
	free(q);

	return 0;
}

void usage(void)
{
	printf("Usage: memloop [options]\n");
	printf(" -n <val>  loop count\n");
	printf(" -b <val>  buffer size (kB)\n");
	printf(" -q        quiet mode\n");
}

int main(int argc, char **argv)
{
	int opt;
	int lp = 10;
	int size = BUFSIZE * 1024;
	int verbose = 1;
	unsigned long ave = 0, min = -1, max = 0;
	unsigned long st, ed;
	int i, j;

	while ((opt = getopt(argc, argv, "n:b:q")) != -1) {
		switch (opt) {
		case 'n':
			lp = atoi(optarg);
			break;
		case 'b':
			size = atoi(optarg) * 1024;
			break;
		case 'q':
			verbose = 0;
			break;
		default:
			usage();
			return -1;
		}
	}

	printf("loop count = %d\n", lp);
	printf("buffer size = %dkB\n", size/1024);

	// 初回は処理時間がかかるのでダミー実行
	for (i=0; i<LP_COUNT; i++) {
		mem_func(size);
	}

	// 計測実処理
	for (j=0; j<lp; j++) {
		st = gettimestamp();	// 開始時刻
		for (i=0; i<LP_COUNT; i++) {
			mem_func(size);
		}
		ed = gettimestamp();	// 終了時刻
		ave = ave + (ed-st);
		if (min > ed-st) {
			min = ed-st;
		}
		if (max < ed-st) {
			max = ed-st;
		}
		if (verbose) {
			printf("time[%d] = %ld, ave = %.2f\n", j, ed-st, (double)ave/(j+1));
		}
	}
	printf("ave = %.2f, min = %ld, max = %ld [us]\n", (double)ave/j, min, max);

	return 0;
}
