• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
main(int ac,char * av[])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 
atoik(char * s)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 
Malloc(size_t sz)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 
tstart(void)321 void tstart(void)
322 {
323 	gettimeofday(&_tstart, NULL);
324 }
325 
tend(void)326 void tend(void)
327 {
328 	gettimeofday(&_tend, NULL);
329 }
330 
tval()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