1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied, modified
8 or distributed except as expressly authorized under the terms of that
9 license. Refer to licensing information at http://www.artifex.com/
10 or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11 San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
12 */
13
14 /* $Id: bench.c 8022 2007-06-05 22:23:38Z giles $ */
15 /* Simple hardware benchmarking suite (C and PostScript) */
16 #include "stdio_.h"
17 #include <stdlib.h>
18
19 /* Patchup for GS externals */
20 FILE *gs_stdout;
21 FILE *gs_stderr;
22 FILE *gs_debug_out;
23 const char gp_scratch_file_name_prefix[] = "gs_";
24 static void
capture_stdio(void)25 capture_stdio(void)
26 {
27 gs_stdout = stdout;
28 gs_stderr = stderr;
29 gs_debug_out = stderr;
30 }
31 #include "gsio.h"
32 #undef gs_stdout
33 #undef gs_stderr
34 #undef stdout
35 #define stdout gs_stdout
36 #undef stderr
37 #define stderr gs_stderr
38 FILE *
gp_open_scratch_file(const char * prefix,char * fname,const char * mode)39 gp_open_scratch_file(const char *prefix, char *fname, const char *mode)
40 {
41 return NULL;
42 }
43 void
gp_set_printer_binary(int prnfno,int binary)44 gp_set_printer_binary(int prnfno, int binary)
45 {
46 }
47 void
gs_to_exit(int n)48 gs_to_exit(int n)
49 {
50 }
51 #define eprintf_program_ident(f, pn, rn) (void)0
52 void
lprintf_file_and_line(FILE * f,const char * file,int line)53 lprintf_file_and_line(FILE * f, const char *file, int line)
54 {
55 fprintf(f, "%s(%d): ", file, line);
56 }
57
58 /*
59 * Read the CPU time (in seconds since an implementation-defined epoch)
60 * into ptm[0], and fraction (in nanoseconds) into ptm[1].
61 */
62 #include "gp_unix.c"
63 #undef stdout
64 #define stdout gs_stdout
65 #undef stderr
66 #define stderr gs_stderr
67
68 /* Loop unrolling macros */
69 #define do10(x) x;x;x;x;x; x;x;x;x;x
70
71 /* Define the actual benchmarks. */
72 static int
iadd(int a,int n,char ** msg)73 iadd(int a, int n, char **msg)
74 {
75 int b = 0, i;
76
77 for (i = n / 20; --i >= 0;) {
78 do10((b += a, b += i));
79 }
80 *msg = "integer adds";
81 return b;
82 }
83 static int
imul(int a,int n,char ** msg)84 imul(int a, int n, char **msg)
85 {
86 int b = 1, i;
87
88 for (i = n / 20; --i > 0;) {
89 do10((b *= a, b *= i));
90 }
91 *msg = "integer multiplies";
92 return b;
93 }
94 static int
idiv(int a,int n,char ** msg)95 idiv(int a, int n, char **msg)
96 {
97 int b = 1, i;
98
99 for (i = n / 20; --i > 0;) {
100 b += 999999;
101 do10((b /= a, b /= i));
102 }
103 *msg = "integer divides";
104 return b;
105 }
106 static int
fadd(float a,int n,char ** msg)107 fadd(float a, int n, char **msg)
108 {
109 float b = 0;
110 int i;
111
112 for (i = n / 10; --i >= 0;) {
113 do10((b += a));
114 }
115 *msg = "floating adds";
116 return b;
117 }
118 static int
fmul(float a,int n,char ** msg)119 fmul(float a, int n, char **msg)
120 {
121 float b = 1;
122 int i;
123
124 for (i = n / 10; --i >= 0;) {
125 do10((b *= a));
126 }
127 *msg = "floating multiplies";
128 return b;
129 }
130 static int
fdiv(float a,int n,char ** msg)131 fdiv(float a, int n, char **msg)
132 {
133 float b = 1;
134 int i;
135
136 for (i = n / 10; --i >= 0;) {
137 do10((b /= a));
138 }
139 *msg = "floating divides";
140 return b;
141 }
142 static int
fconv(int a,int n,char ** msg)143 fconv(int a, int n, char **msg)
144 {
145 int b[10];
146 float f[10];
147 int i;
148
149 b[0] = a;
150 for (i = n / 20; --i >= 0;)
151 f[0] = b[0], f[1] = b[1], f[2] = b[2], f[3] = b[3], f[4] = b[4],
152 f[5] = b[5], f[6] = b[6], f[7] = b[7], f[8] = b[8], f[9] = b[9],
153 b[0] = f[1], b[1] = f[2], b[2] = f[3], b[3] = f[4], b[4] = f[5],
154 b[5] = f[6], b[6] = f[7], b[7] = f[8], b[8] = f[9], b[9] = f[0];
155 *msg = "float/int conversions";
156 return b[0];
157 }
158 static int
mfast(int * m,int n,char ** msg)159 mfast(int *m, int n, char **msg)
160 {
161 int i;
162
163 m[0] = n;
164 for (i = n / 20; --i >= 0;)
165 m[9] = m[8], m[8] = m[7], m[7] = m[6], m[6] = m[5], m[5] = m[4],
166 m[4] = m[3], m[3] = m[2], m[2] = m[1], m[1] = m[0], m[0] = m[9];
167 *msg = "fast memory accesses";
168 return m[0];
169 }
170 static int
mslow(int * m,int n,char ** msg)171 mslow(int *m, int n, char **msg)
172 {
173 int *p;
174 int i, k = 0;
175
176 m[0] = n;
177 for (i = n / 20; --i >= 0; k = (k + 397) & 0x3ffff)
178 p = m + k,
179 p[0] = p[100], p[20] = p[120], p[40] = p[140],
180 p[60] = p[160], p[80] = p[180],
181 p[200] = p[300], p[220] = p[320], p[240] = p[340],
182 p[260] = p[360], p[280] = p[380];
183 *msg = "slow memory accesses";
184 return m[0];
185 }
186
187 int
main(int argc,const char * argv[])188 main(int argc, const char *argv[])
189 {
190 int i;
191 int *mem = malloc(1100000);
192
193 capture_stdio();
194 for (i = 0;; ++i) {
195 long t0[2], t1[2];
196 char *msg;
197 int n;
198
199 gp_get_usertime(t0);
200 switch (i) {
201 case 0:
202 iadd(0, n = 10000000, &msg);
203 break;
204 case 1:
205 imul(1, n = 1000000, &msg);
206 break;
207 case 2:
208 idiv(1, n = 1000000, &msg);
209 break;
210 case 3:
211 fadd(3.14, n = 10000000, &msg);
212 break;
213 case 4:
214 fmul(1.0000001, n = 10000000, &msg);
215 break;
216 case 5:
217 fdiv(1.0000001, n = 1000000, &msg);
218 break;
219 case 6:
220 fconv(12345, n = 10000000, &msg);
221 break;
222 case 7:
223 mfast(mem, n = 10000000, &msg);
224 break;
225 case 8:
226 mslow(mem, n = 1000000, &msg);
227 break;
228 default:
229 free(mem);
230 exit(0);
231 }
232 gp_get_usertime(t1);
233 fprintf(stdout, "Time for %9d %s = %g ms\n", n, msg,
234 (t1[0] - t0[0]) * 1000.0 + (t1[1] - t0[1]) / 1000000.0);
235 fflush(stdout);
236 }
237 }
238
239 /*
240 Output from SPARCstation 10, gcc -O bench.c gp_unix.c:
241
242 Time for 10000000 integer adds = 113.502 ms
243 Time for 1000000 integer multiplies = 467.965 ms
244 Time for 1000000 integer divides = 594.328 ms
245 Time for 10000000 floating adds = 641.21 ms
246 Time for 10000000 floating multiplies = 643.357 ms
247 Time for 1000000 floating divides = 131.995 ms
248 Time for 10000000 float/int conversions = 602.061 ms
249 Time for 10000000 fast memory accesses = 201.048 ms
250 Time for 1000000 slow memory accesses = 552.606 ms
251
252 Output from 486DX/25, wcl386 -oit bench.c gp_iwatc.c gp_msdos.c:
253
254 Time for 10000000 integer adds = 490 ms
255 Time for 1000000 integer multiplies = 770 ms
256 Time for 1000000 integer divides = 1860 ms
257 Time for 10000000 floating adds = 4070 ms
258 Time for 10000000 floating multiplies = 4450 ms
259 Time for 1000000 floating divides = 2470 ms
260 Time for 10000000 float/int conversions = 25650 ms
261 Time for 10000000 fast memory accesses = 990 ms
262 Time for 1000000 slow memory accesses = 330 ms
263
264 */
265
266 /*
267 The rest of this file contains a similar benchmark in PostScript.
268
269 %!
270 /timer % <str> <N> <proc> timer
271 { bind 2 copy usertime mark 4 2 roll repeat cleartomark usertime exch sub
272 % Stack: str N proc dt
273 exch pop
274 (Time for ) print exch =only ( ) print exch =only (: ) print
275 =only ( ms
276 ) print flush
277 } def
278
279 (x 20 integer adds) 5000 { 0
280 0 add 0 add 0 add 0 add 0 add 0 add 0 add 0 add 0 add 0 add
281 0 add 0 add 0 add 0 add 0 add 0 add 0 add 0 add 0 add 0 add
282 pop } timer
283
284 (x 20 integer multiplies) 5000 { 1
285 3 mul 3 mul 3 mul 3 mul 3 mul 3 mul 3 mul 3 mul 3 mul 3 mul
286 3 mul 3 mul 3 mul 3 mul 3 mul 3 mul 3 mul 3 mul 3 mul 3 mul
287 pop } timer
288
289 (x 20 integer divides) 5000 { 1000000000
290 3 idiv 3 idiv 3 idiv 3 idiv 3 idiv 3 idiv 3 idiv 3 idiv 3 idiv 3 idiv
291 3 idiv 3 idiv 3 idiv 3 idiv 3 idiv 3 idiv 3 idiv 3 idiv 3 idiv 3 idiv
292 pop } timer
293
294 (x 20 floating adds) 5000 { 0.0
295 1.0 add 1.0 add 1.0 add 1.0 add 1.0 add 1.0 add 1.0 add 1.0 add 1.0 add 1.0 add
296 1.0 add 1.0 add 1.0 add 1.0 add 1.0 add 1.0 add 1.0 add 1.0 add 1.0 add 1.0 add
297 pop } timer
298
299 (x 20 floating multiplies) 5000 { 1.0
300 2.3 mul 2.3 mul 2.3 mul 2.3 mul 2.3 mul 2.3 mul 2.3 mul 2.3 mul 2.3 mul 2.3 mul
301 2.3 mul 2.3 mul 2.3 mul 2.3 mul 2.3 mul 2.3 mul 2.3 mul 2.3 mul 2.3 mul 2.3 mul
302 pop } timer
303
304 (x 20 floating divides) 5000 { 1.0
305 2.3 div 2.3 div 2.3 div 2.3 div 2.3 div 2.3 div 2.3 div 2.3 div 2.3 div 2.3 div
306 2.3 div 2.3 div 2.3 div 2.3 div 2.3 div 2.3 div 2.3 div 2.3 div 2.3 div 2.3 div
307 pop } timer
308
309 (x 20 float/int conversions) 5000 { 12345.0
310 cvi cvr cvi cvr cvi cvr cvi cvr cvi cvr
311 cvi cvr cvi cvr cvi cvr cvi cvr cvi cvr
312 pop } timer
313
314 /S 2048 string def
315 (x 10000(byte) fast memory accesses) 1000 {
316 //S 1024 1000 getinterval //S copy pop
317 //S 1024 1000 getinterval //S copy pop
318 //S 1024 1000 getinterval //S copy pop
319 //S 1024 1000 getinterval //S copy pop
320 //S 1024 1000 getinterval //S copy pop
321 } timer
322
323 /A [ 500 { 2048 string } repeat ] def
324 (x 500 x 2000(byte) slower memory accesses) 10 {
325 0 1 499 {
326 //A exch get dup 1024 1000 getinterval exch copy pop
327 } for
328 } timer
329
330 /Times-Roman findfont 36 scalefont setfont
331 currentcacheparams pop pop 0 1 index setcacheparams
332 /D [4 0 0 4 0 0] 1440 1440 <00 ff> makeimagedevice def
333 D setdevice
334 72 72 translate
335 gsave 15 rotate
336 0 0 moveto (A) show
337 (x 10 (A) show (cache)) 100 {
338 0 0 moveto
339 (A) show (A) show (A) show (A) show (A) show
340 (A) show (A) show (A) show (A) show (A) show
341 } timer grestore
342
343 0 setcachelimit
344 gsave 10 rotate
345 (x 10 (A) show (no cache)) 10 {
346 0 0 moveto
347 (A) show (A) show (A) show (A) show (A) show
348 (A) show (A) show (A) show (A) show (A) show
349 } timer grestore
350
351 quit
352
353 Results for SUN Sparc 2 (rated at 25 MIPS according to manual)
354
355 ./gs
356 Now in gs_init.ps
357 TextAlphaBits defined GraphicsAlphaBits defined
358 Aladdin Ghostscript 3.50 (1995-9-24)
359 (c) 1995 Aladdin Enterprises, Menlo Park, CA. All rights reserved. This
360 software comes with NO WARRANTY: see the file PUBLIC for details. Leaving
361 gs_init.ps
362 GS>(ben1.c) run
363 Time for 5000 x 20 integer adds: 171 ms
364 Time for 5000 x 20 integer multiplies: 504 ms
365 Time for 5000 x 20 integer divides: 334 ms
366 Time for 5000 x 20 floating adds: 148 ms
367 Time for 5000 x 20 floating multiplies: 165 ms
368 Time for 5000 x 20 floating divides: 194 ms
369 Time for 5000 x 20 float/int conversions: 121 ms
370 Time for 1000 x 10000(byte) fast memory accesses: 112 ms
371 Time for 10 x 500 x 2000(byte) slower memory accesses: 236 ms
372 Loading NimbusRomanNo9L-Regular font from
373 [...]/n021003l.gsf... 1739080 414724 2564864 1251073 0
374 done. Time for 100 x 10 (A) show (cache): 144 ms
375 Time for 10 x 10 (A) show (no cache): 538 ms
376
377 Output from SPARCstation 10, gs 3.60 compiled with gcc -g -O -DDEBUG:
378
379 gsnd bench.c
380 Aladdin Ghostscript 3.60 (1995-10-23)
381 Copyright (C) 1995 Aladdin Enterprises, Menlo Park, CA. All rights reserved.
382 This software comes with NO WARRANTY: see the file PUBLIC for details.
383 Time for 5000 x 20 integer adds: 192 ms
384 Time for 5000 x 20 integer multiplies: 561 ms
385 Time for 5000 x 20 integer divides: 396 ms
386 Time for 5000 x 20 floating adds: 202 ms
387 Time for 5000 x 20 floating multiplies: 247 ms
388 Time for 5000 x 20 floating divides: 243 ms
389 Time for 5000 x 20 float/int conversions: 157 ms
390 Time for 1000 x 10000(byte) fast memory accesses: 136 ms
391 Time for 10 x 500 x 2000(byte) slower memory accesses: 235 ms
392 Loading Temps-RomanSH font from /opt/home/peter/gs/fonts/soho/tersh___.pfb... 1759156 432729 2564864 1251025 0 done.
393 Time for 100 x 10 (A) show (cache): 161 ms
394 Time for 10 x 10 (A) show (no cache): 449 ms
395
396 Output from 486DX/25, gs 2.6.1 compiled with wcc386 -oi[t]:
397
398 gsndt bench.c
399 Initializing... done.
400 Ghostscript 2.6.1 (5/28/93)
401 Copyright (C) 1990-1993 Aladdin Enterprises, Menlo Park, CA.
402 All rights reserved.
403 Ghostscript comes with NO WARRANTY: see the file COPYING for details.
404 Time for 5000 x 20 integer adds: 550 ms
405 Time for 5000 x 20 integer multiplies: 940 ms
406 Time for 5000 x 20 integer divides: 880 ms
407 Time for 5000 x 20 floating adds: 550 ms
408 Time for 5000 x 20 floating multiplies: 660 ms
409 Time for 5000 x 20 floating divides: 930 ms
410 Time for 5000 x 20 float/int conversions: 830 ms
411 Time for 1000 x 10000(byte) fast memory accesses: 660 ms
412 Time for 10 x 500 x 2000(byte) slower memory accesses: 540 ms
413 Loading Temps-RomanSH font from c:\gs\fonts\softhorz\tersh___.pfb... 1298792 1207949 0 done.
414 Time for 100 x 10 (A) show (cache): 13520 ms
415 Time for 10 x 10 (A) show (no cache): 1310 ms
416
417 Output from 486DX/25, gs 3.52 compiled with wcc386 -oi[t]:
418
419 Aladdin Ghostscript 3.52 (1995-10-2)
420 Copyright (c) 1995 Aladdin Enterprises, Menlo Park, CA. All rights reserved.
421 This software comes with NO WARRANTY: see the file PUBLIC for details.
422 Time for 5000 x 20 integer adds: 660 ms
423 Time for 5000 x 20 integer multiplies: 1100 ms
424 Time for 5000 x 20 integer divides: 940 ms
425 Time for 5000 x 20 floating adds: 710 ms
426 Time for 5000 x 20 floating multiplies: 830 ms
427 Time for 5000 x 20 floating divides: 1040 ms
428 Time for 5000 x 20 float/int conversions: 820 ms
429 Time for 1000 x 10000(byte) fast memory accesses: 660 ms
430 Time for 10 x 500 x 1000(byte) slower memory accesses: 600 ms
431 Loading Temps-RomanSH font from c:\gs\fonts\softhorz\tersh___.pfb... 1678548 375231 2564864 1250964 0 done.
432 Time for 100 x 10 (A) show (cache): 2520 ms
433 Time for 10 x 10 (A) show (no cache): 1600 ms
434
435 */
436