xref: /plan9/sys/src/cmd/gs/src/bench.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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