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