Home | History | Annotate | Download | only in memxfer5b
      1 /* Memory streaming benchmark */
      2 
      3 /*
      4  * Copyright (C) 2003-2006 IBM
      5  *
      6  * This program is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU General Public License as
      8  * published by the Free Software Foundation; either version 2 of the
      9  * License, or (at your option) any later version.
     10  *
     11  * This program is distributed in the hope that it will be useful, but
     12  * WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the GNU
     14  * General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU General Public License
     17  * along with this program; if not, write to the Free Software
     18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
     19  * 02111-1307, USA.
     20  */
     21 
     22 #define __int64 long long
     23 #include <sys/time.h>
     24 #define SLASHC		'/'
     25 #define SLASHSTR	"/"
     26 #include <sys/types.h>
     27 #include <string.h>
     28 #include <stddef.h>
     29 #include <stdlib.h>
     30 #include <stdio.h>
     31 #include <ctype.h>
     32 
     33 #define equal !strcmp
     34 
     35 size_t atoik(char *);
     36 void *Malloc(size_t sz);
     37 void tstart(void);
     38 void tend(void);
     39 double tval(void);
     40 
     41 char *methods[] = {
     42 	"\"memcpy\"",
     43 	"\"char *\"",
     44 	"\"short *\"",
     45 	"\"int *\"",
     46 	"\"long *\"",
     47 	"\"__int64 *\"",
     48 	"\"double *\"",
     49 };
     50 
     51 int nmethods = sizeof(methods) / sizeof(methods[0]);
     52 
     53 int fflag = 0;			// if 0, then just Malloc once; else malloc/free each time
     54 int wflag = 0;			// if 1, call SetProcessWorkingSetSize() (WINDOWS ONLY)
     55 int sflag = 0;			// if 1, only print averages.
     56 int pflag = 0;
     57 int csvflag = 0;		// Print Comma separated list for spreadsheet input.
     58 char *progname;
     59 
     60 double tottim = 0.0;
     61 
     62 int main(int ac, char *av[])
     63 {
     64 	size_t size;
     65 	int i;
     66 	unsigned ui;
     67 	size_t j;
     68 	unsigned cnt;
     69 	int method = 0;
     70 	char *p1, *p2;
     71 	char *p, *q;
     72 	short *sp, *sq;
     73 	int *ip, *iq;
     74 	long *lp, *lq;
     75 	__int64 *llp, *llq;
     76 	double *dp, *dq;
     77 	double t;
     78 
     79 	progname = av[0];
     80 	if (strrchr(progname, SLASHC))
     81 		progname = strrchr(progname, SLASHC) + 1;
     82 
     83 	while (ac > 1) {
     84 		if (equal(av[1], "-f")) {
     85 			ac--;
     86 			fflag = 1;
     87 			av++;
     88 		} else if (equal(av[1], "-w")) {
     89 			ac--;
     90 			wflag = 1;
     91 			av++;
     92 		} else if (equal(av[1], "-s")) {
     93 			ac--;
     94 			sflag = 1;
     95 			av++;
     96 		} else if (equal(av[1], "-p")) {
     97 			ac--;
     98 			pflag = 1;
     99 			av++;
    100 		} else if (equal(av[1], "-csv")) {
    101 			ac--;
    102 			csvflag++;
    103 			av++;
    104 		} else
    105 			break;
    106 	}
    107 	if (ac < 3) {
    108 		(void)
    109 		    printf("Usage: %s [-f] [-w] [-s] [-p] size cnt [method]\n",
    110 			   progname);
    111 		(void)
    112 		    printf
    113 		    ("\t-f flag says to malloc and free of the \"cnt\" times.\n");
    114 		(void)
    115 		    printf
    116 		    ("\t-w = set process min and max working set size to \"size\"\n");
    117 		(void)printf("\t-s = silent; only print averages\n");
    118 		(void)
    119 		    printf
    120 		    ("\t-p = prep; \"freshen\" cache before; -w disables\n");
    121 		(void)printf("\t-csv = print output in CSV format\n");
    122 
    123 		(void)printf("\tmethods:\n");
    124 		for (i = 0; i < nmethods; i++)
    125 			printf("\t%2d:\t%s\n", i, methods[i]);
    126 		return 0;
    127 	}
    128 
    129 	size = atoik(av[1]);
    130 
    131 	//
    132 	// Round size up to 4*sizeof(double) bytes.
    133 	//
    134 	if (size != ((size / (4 * sizeof(double))) * (4 * sizeof(double)))) {
    135 		size += (4 * sizeof(double));
    136 		size /= (4 * sizeof(double));
    137 		size *= (4 * sizeof(double));
    138 	}
    139 	cnt = (unsigned)atoik(av[2]);
    140 
    141 	if (fflag == 0) {
    142 		p1 = (char *)Malloc(size);
    143 		p2 = (char *)Malloc(size);
    144 		if (pflag)
    145 			memcpy(p1, p2, size);
    146 	}
    147 
    148 	printf("%s ", progname);
    149 	if (fflag)
    150 		printf("-f ");
    151 	if (wflag)
    152 		printf("-w ");
    153 	if (sflag)
    154 		printf("-s ");
    155 	if (pflag)
    156 		printf("-p ");
    157 	if (csvflag)
    158 		printf("-csv ");
    159 	printf("%u %u ", size, cnt);
    160 	if (csvflag) {
    161 		printf("Linux");
    162 	}
    163 	printf("\n");
    164 
    165 	if (ac == 3) {
    166 		ac = 4;
    167 		av[3] = "0";
    168 	}
    169 
    170 	for (; ac > 3; ac--, av++) {
    171 		if (isdigit(*av[3]))
    172 			method = *av[3] - '0';
    173 		if (method < 0 || method >= nmethods)
    174 			method = 0;
    175 		if (sflag)
    176 			tstart();
    177 		for (ui = 0; ui < cnt; ui++) {
    178 			if (!sflag) {
    179 				(void)printf("%s %d %d %-18.18s\t",
    180 					     progname, size, cnt,
    181 					     methods[method]);
    182 				tstart();
    183 			}
    184 			if (fflag == 1) {
    185 				p1 = (char *)Malloc(size);
    186 				p2 = (char *)Malloc(size);
    187 			}
    188 			switch (method) {
    189 			case 0:
    190 				(void)memcpy(p1, p2, size);
    191 				break;
    192 			case 1:
    193 				p = p1;
    194 				q = p2;
    195 				for (j = 0; j < size; j++)
    196 					*p++ = *q++;
    197 				break;
    198 			case 2:
    199 				sp = (short *)p1;
    200 				sq = (short *)p2;
    201 				for (j = 0; j < size; j += sizeof(short))
    202 					*sp++ = *sq++;
    203 				break;
    204 			case 3:
    205 				ip = (int *)p1;
    206 				iq = (int *)p2;
    207 				for (j = 0; j < size; j += sizeof(int))
    208 					*ip++ = *iq++;
    209 				break;
    210 			case 4:
    211 				lp = (long *)p1;
    212 				lq = (long *)p2;
    213 				for (j = 0; j < size; j += sizeof(long))
    214 					*lp++ = *lq++;
    215 				break;
    216 			case 5:
    217 				llp = (__int64 *) p1;
    218 				llq = (__int64 *) p2;
    219 				for (j = 0; j < size; j += sizeof(__int64))
    220 					*llp++ = *llq++;
    221 				break;
    222 			case 6:
    223 				dp = (double *)p1;
    224 				dq = (double *)p2;
    225 				for (j = 0; j < size; j += 4 * sizeof(double)) {
    226 					*dp++ = *dq++;
    227 					*dp++ = *dq++;
    228 					*dp++ = *dq++;
    229 					*dp++ = *dq++;
    230 				}
    231 				break;
    232 
    233 			}
    234 			if (fflag == 1) {
    235 				free(p1);
    236 				free(p2);
    237 			}
    238 			if (!sflag) {
    239 				tend();
    240 				t = tval();
    241 				tottim += t;
    242 				if (t == 0.0)
    243 					t = .0001;
    244 				printf(" %8.6f seconds %8.3f MB/s\n",
    245 				       t, (double)size / t / 1000000.);
    246 			}
    247 		}
    248 		if (sflag) {
    249 			tend();
    250 			tottim = tval();
    251 		}
    252 		if (csvflag) {
    253 			printf("%s,%u,%u,%8.3f,%8.3f\n",
    254 			       methods[method], size, size * cnt, tottim,
    255 			       (double)size / (tottim / cnt) / 1000000.);
    256 		} else {
    257 			(void)printf("\tAVG: %d %-18.18s\t", size,
    258 				     methods[method]);
    259 			(void)printf(" %8.3f MB/s\n",
    260 				     (double)size / (tottim / cnt) / 1000000.);
    261 		}
    262 		tottim = 0.0;
    263 	}
    264 	return 0;
    265 }
    266 
    267 size_t atoik(char *s)
    268 {
    269 	size_t ret = 0;
    270 	size_t base;
    271 
    272 	if (*s == '0') {
    273 		base = 8;
    274 		if (*++s == 'x' || *s == 'X') {
    275 			base = 16;
    276 			s++;
    277 		}
    278 	} else
    279 		base = 10;
    280 
    281 	for (; isxdigit(*s); s++) {
    282 		if (base == 16)
    283 			if (isalpha(*s))
    284 				ret = base * ret + (toupper(*s) - 'A');
    285 			else
    286 				ret = base * ret + (*s - '0');
    287 		else if (isdigit(*s))
    288 			ret = base * ret + (*s - '0');
    289 		else
    290 			break;
    291 	}
    292 	for (; isalpha(*s); s++) {
    293 		switch (toupper(*s)) {
    294 		case 'K':
    295 			ret *= 1024;
    296 			break;
    297 		case 'M':
    298 			ret *= 1024 * 1024;
    299 			break;
    300 		default:
    301 			return ret;
    302 		}
    303 	}
    304 	return ret;
    305 }
    306 
    307 void *Malloc(size_t sz)
    308 {
    309 	char *p;
    310 
    311 	p = (char *)malloc(sz);
    312 	if (p == NULL) {
    313 		(void)printf("malloc(%d) failed\n", sz);
    314 		exit(1);
    315 	}
    316 	return (void *)p;
    317 }
    318 
    319 static struct timeval _tstart, _tend;
    320 
    321 void tstart(void)
    322 {
    323 	gettimeofday(&_tstart, NULL);
    324 }
    325 
    326 void tend(void)
    327 {
    328 	gettimeofday(&_tend, NULL);
    329 }
    330 
    331 double tval()
    332 {
    333 	double t1, t2;
    334 
    335 	t1 = (double)_tstart.tv_sec + (double)_tstart.tv_usec / (1000 * 1000);
    336 	t2 = (double)_tend.tv_sec + (double)_tend.tv_usec / (1000 * 1000);
    337 	return t2 - t1;
    338 }
    339