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

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

        //printf ( "argv[1] = %s\n", argv[1] );
        //printf ( "argv[2] = %s\n", argv[2] );
	//int empty1;
	//int size1;
	//int size2;
	//size1 = atoi (argv[1]);
	//printf ( "size1: %d\n", size1);
        //printf ( "sizeof int: %d\n", sizeof(int));
        struct timeval starttime,endtime;
        double te;
        long t, t2; 
int long_size=sizeof(long);
printf("long size: %d\n", long_size);
long asize = 68 * 1024 * 1024 / long_size;
long array_bytes=asize*long_size;
        long block_size;
	long *a;
	//long *b;
	//a=calloc(1610612736, 4);

	//allocate 1200MB a peice (2.4GB total) two zero-initialized memory blocks
	//printf ( "allocating 1200MB a peice (2.4GB total) two zero-initialized memory blocks\n"); 
	//gettimeofday(&starttime, NULL);
a=calloc(asize, long_size);
	//b=calloc(asize, long_size);
	//gettimeofday(&endtime, NULL);
	//te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
	//printf ( "\tTime: %lfMB/s\n", 2400/te);

	//write data to allocated memory


//	printf ( "change all values of allocated memory 1 element at a time\n");
//	gettimeofday(&starttime, NULL);
        for(t=0; t<asize; t++) {
                a[t]=0xaa;
		//b[t]=0xab;
        }
	printf ( "Block size:\tTime:\n\n");
	for(block_size=1 * 1024 / long_size; block_size<array_bytes; block_size=block_size*2) {
        	//for(t2=0; t2<block_size; t2++) {
                	//a[t]=0xaa;
                	//b[t]=0xab;
			//memmove (a,a,block_size);
			gettimeofday(&starttime, NULL);
			for(t2=0; t2<1000000; t2++) {
				memcpy (a,a,block_size);
				memmove (a,a,block_size);
				memcpy (a,a,block_size);
				memmove (a,a,block_size);
			}
			gettimeofday(&endtime, NULL);	
			te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec));
			printf ( "%ld\t%lf\n", block_size, te);
        	//}
	}

//memmove (str+t2,str+t2,t2);
/*	gettimeofday(&endtime, NULL);
	te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
	printf ( "\tTime: %lfMB/s\n", 2400/te);
//system("free -m");
	//copy array a to array b
	printf ( "copy array a to array b\n");
	gettimeofday(&starttime, NULL);
	memcpy(b,a,array_bytes);
	gettimeofday(&endtime, NULL);
	te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
	printf ( "\tTime: %lfMB/s\n", 1200/te);
//system("free -m");

	//copy array a to array b in steps
	//1MB block size
	printf ( "copy array a to array b in incrementing steps of 32MB\n");
	block_size= 32 * 1024 * 1024 / long_size;;
	gettimeofday(&starttime, NULL);
	for(t=0; t<array_bytes; t+=block_size) {
        	mempcpy(b,a,t);
        }
	gettimeofday(&endtime, NULL);
        te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
        
	t2 = 0;
        for(t=0; t<array_bytes; t+=block_size) {
               t2+=t; 
        }
	printf ( "\tTime: %lfMB/s\n", (t2/1024/1024)/te);

//system("free -m");
	//32MB block size
	printf ( "copy array a to array b in incrementing steps of 128MB\n");
        block_size=128 * 1024 * 1024 / long_size;;
	gettimeofday(&starttime, NULL);
        for(t=0; t<array_bytes; t+=block_size) {
                mempcpy(b,a,t);
        }
        gettimeofday(&endtime, NULL); 
        te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
        t2 = 0;
        for(t=0; t<array_bytes; t+=block_size) {
               t2+=t;
        }
        printf ( "\tTime: %lfMB/s\n", (t2/1024/1024)/te);


//system("free -m");
	//copy array a to array b 1 element at a time "dumb test"
	printf ( "copy array a to array b 1 element at a time (dumb test)\n");
	gettimeofday(&starttime, NULL);
        for(t=0; t<asize; t++) {
        	b[t]=a[t];
        }
        gettimeofday(&endtime, NULL);
        te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
	printf ( "\tTime: %lfMB/s\n", 1200/te);
//system("free -m");

	//free arrays
	printf ( "free arrays\n");
	gettimeofday(&starttime, NULL);
	free (a);
	free (b);
        gettimeofday(&endtime, NULL);
        te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
        printf ( "\tTime: %lf\n", te);
//system("free -m");
*/
	printf ( "Done.\n");
free(a);
	//size2 = 1024 / 4; 
	//int array1[(size1*1024)/sizeof(int)];

	//int array1[268435456];
	//size2 = sizeof(array1);
	//printf ( "array1: %d\n", sizeof(array1));
	//sleep (240);

	return 0;
}
