185 lines
6.2 KiB
Plaintext
185 lines
6.2 KiB
Plaintext
.so init
|
|
.SH
|
|
A. MEASUREMENTS
|
|
.SH
|
|
A.1. \*(OQThe bottom line\*(CQ
|
|
.PP
|
|
Although examples often are most illustrative, the cruel world out there is
|
|
usually more interested in everyday performance figures. To satisfy those
|
|
people too, we will present a series of measurements on our code expander
|
|
taken from (close to) real life situations. These include measurements
|
|
of compile and run times of different programs,
|
|
compiled with different compilers.
|
|
.SH
|
|
A.2. Compile time measurements
|
|
.PP
|
|
Figure A.2.1 shows compile-time measurements for typical C code:
|
|
the dhrystone benchmark\(dg
|
|
.[ [
|
|
dhrystone
|
|
.]].
|
|
.FS
|
|
\(dg To be certain that we only tested the compiler and not the quality of
|
|
the code in the library, we have added our own version of
|
|
\fIstrcmp\fR and \fIstrcpy\fR and have not used the ones present in the
|
|
library.
|
|
.FE
|
|
The numbers represent the duration of each separate pass of the compiler.
|
|
The numbers at the end of each bar represent the total duration of the
|
|
compilation process. As with all measurements in this chapter, the
|
|
quoted time or duration is the sum of user and system time in seconds.
|
|
.PS
|
|
copy "pics/compile_bars"
|
|
.PE
|
|
.DS
|
|
.IP cem: 6
|
|
C to EM frontend
|
|
.IP opt:
|
|
EM peep-hole optimizer
|
|
.IP be:
|
|
EM to assembler backend
|
|
.IP cpp:
|
|
Sun's C preprocessor
|
|
.IP ccom:
|
|
Sun's C compiler
|
|
.IP iropt:
|
|
Sun's optimizer
|
|
.IP cg:
|
|
Sun's code generator
|
|
.IP as:
|
|
Sun's assembler
|
|
.IP ld:
|
|
Sun's linker
|
|
.ce 1
|
|
\fIFigure A.2.1: compile-time measurements.\fR
|
|
.DE
|
|
.sp
|
|
.PP
|
|
A close examination of the first two bars in fig A.2.1 shows that the maximum
|
|
achievable compile-time
|
|
gain compared to \fIcc\fR is about 50% for medium-sized
|
|
programs.\(dd
|
|
.FS
|
|
\(dd (cpp+ccom+as+ld)/(cem+as+ld) = 1.53
|
|
.FE
|
|
For small programs the gain will be less, due to the almost constant
|
|
start-up time of each pass in the compilation process. Only a
|
|
built-in assembler may increase this number up to
|
|
180% in the ideal case that the optimizer, backend and assembler
|
|
would run in zero time. Speed-ups of 5 to 10 times as mentioned in
|
|
.[ [
|
|
fast portable compilers
|
|
.]]
|
|
are therefore not possible on the Sun-4 family. This is also due to
|
|
Sun's implementation of saving and restoring register windows. With
|
|
the current implementation in which only a single window is saved
|
|
or restored on a register-window overflow, it is very time consuming
|
|
when programs have highly dynamic stack use
|
|
due to procedure calls (as is often the case with compilers).
|
|
.PP
|
|
Although we are currently a little slower than \fIcc\fR, it is hard to
|
|
blame this on our backend. Optimizing the backend so that it would run
|
|
twice as fast would only reduce the total compilation process by
|
|
a mere 14%.
|
|
.PP
|
|
Finally it is nice to see that our push/pop-optimization,
|
|
initially designed to generate faster code, has also increased the
|
|
compilation speed. (see also figures A.4.1 and A.4.2.)
|
|
.SH
|
|
A.3. Run time performance
|
|
.PP
|
|
Figure A.3.1 shows the run-time performance of different compilers.
|
|
All results are normalized, where the best available compiler (Sun's
|
|
compiler with full optimization) is represented by 1.0 on our scale.
|
|
.PS
|
|
copy "pics/run-time_bars"
|
|
.PE
|
|
.ce 1
|
|
\fIFigure A.3.1: run time performance.\fR
|
|
.sp 1
|
|
.PP
|
|
The fact that our compiler behaves rather poorly compared to Sun's
|
|
compiler is due to the fact that the dhrystone benchmark uses
|
|
relatively many subroutine calls; all of which have to be 'emulated'
|
|
by our backend.
|
|
.SH
|
|
A.4. Overall performance
|
|
.LP
|
|
In the next two figures we will show the combined run and compile time
|
|
performance of 'our' compiler (the ACK C frontend and our backend)
|
|
compared to Sun's C compiler. Figure A.4.1 shows the results from
|
|
measurements on the dhrystone benchmark.
|
|
.G1
|
|
frame invis left solid bot solid
|
|
label left "run time" "(in \(*msec/dhrystone)"
|
|
label bot "compile time (in sec)"
|
|
coord x 0,21 y 0,610
|
|
ticks left out from 0 to 600 by 200
|
|
ticks bot out from 0 to 20 by 5
|
|
"\(bu" at 3.5, 1000000/1700
|
|
"ack w/o opt" ljust at 3.5 + 1, 1000000/1700
|
|
"\(bu" at 2.8, 1000000/8770
|
|
"ack with opt" below at 2.8 + 0.1, 1000000/8770
|
|
"\(bu" at 16.0, 1000000/10434
|
|
"ack -O4" above at 16.0, 1000000/10434
|
|
"\(bu" at 2.3, 1000000/7270
|
|
"\fIcc\fR" above at 2.3, 1000000/7270
|
|
"\(bu" at 9.0, 1000000/12500
|
|
"\fIcc -O4\fR" above at 9.0, 1000000/12500
|
|
"\(bu" at 5.9, 1000000/15250
|
|
"\fIcc -O\fR" below at 5.9, 1000000/15250
|
|
.G2
|
|
.ce 1
|
|
\fIFigure A.4.1: overall performance on dhrystones.
|
|
.sp 1
|
|
.LP
|
|
Fortunately for us, dhrystones are not all there is. The following
|
|
figure shows the same measurements as the previous one, except
|
|
this time we took a benchmark that uses no subroutines: an implementation
|
|
of Eratosthenes' sieve:
|
|
.G1
|
|
frame invis left solid bot solid
|
|
label left "run time" "for one run" "(in sec)" left .6
|
|
label bot "compile time (in sec)"
|
|
coord x 0,11 y 0,21
|
|
ticks bot out from 0 to 10 by 5
|
|
ticks left out from 0 to 20 by 5
|
|
"\(bu" at 2.5, 17.28
|
|
"ack w/o opt" above at 2.5, 17.28
|
|
"\(bu" at 1.6, 2.93
|
|
"ack with opt" above at 1.6, 2.93
|
|
"\(bu" at 9.4, 2.26
|
|
"ack -O4" above at 9.4, 2.26
|
|
"\(bu" at 1.5, 7.43
|
|
"\fIcc\fR" above at 1.5, 7.43
|
|
"\(bu" at 2.7, 2.02
|
|
"\fIcc -O4\fR" ljust at 1.9, 1.2
|
|
"\(bu" at 2.6, 2.10
|
|
"\fIcc -O\fR" ljust at 3.1,2.5
|
|
.G2
|
|
.ce 1
|
|
\fIFigure A.4.2: overall performance on Eratosthenes' sieve.
|
|
.sp 1
|
|
.PP
|
|
Although the above figures speak for themselves, a small comment
|
|
may be in place. At first it is clear that our compiler is neither
|
|
faster than \fIcc\fR, nor produces faster code than \fIcc -O4\fR. It should
|
|
also be noted however, that we do produce better code than \fIcc\fR
|
|
at only a very small additional cost.
|
|
It is also worth noticing that push-pop optimization
|
|
increases run-time speed as well as compile speed.
|
|
The first seems rather obvious,
|
|
since optimized code is
|
|
faster code, but the increase in compile speed may come as a surprise.
|
|
The main reason is that the \fIas\fR+\fIld\fR time depends largely on the
|
|
amount of generated code, which in general
|
|
depends on the efficiency of the code.
|
|
Push-pop optimization removes a lot of useless instructions which
|
|
would otherwise
|
|
have found their way through to the assembler and the loader.
|
|
Useless instructions inserted in an early stage in the compilation
|
|
process will slow down every following stage, so elimination of useless
|
|
instructions in an early stage, even when it requires a little computational
|
|
overhead, can often be beneficial to the overall compilation speed.
|
|
.bp
|