Next: 5.13 Efficiency Notes
Up: 5.12 General Efficiency Hints
Previous: 5.12.4 Mapping and Iteration
In order to write efficient code, you need to know the relative costs
of different operations. The main reason why writing efficient
Common Lisp code is difficult is that there are so many operations, and
the costs of these operations vary in obscure context-dependent ways.
Although efficiency notes point out some problem areas, the only way
to ensure generation of the best code is to look at the assembly code
output.
The disassemble function is a convenient way to get the assembly code for a
function, but it can be very difficult to interpret, since the correspondence
with the original source code is weak. A better (but more awkward) option is
to use the :trace-file argument to compile-file to generate a trace
file.
A trace file is a dump of the compiler's internal representations,
including annotated assembly code. Each component in the program gets
four pages in the trace file (separated by ``''):
- The implicit-continuation (or IR1) representation of the
optimized source. This is a dump of the flow graph representation
used for ``source level'' optimizations. As you will quickly
notice, it is not really very close to the source. This
representation is not very useful to even sophisticated users.
- The Virtual Machine (VM, or IR2) representation of the program.
This dump represents the generated code as sequences of ``Virtual
OPerations'' (VOPs.) This representation is intermediate between
the source and the assembly code--each VOP corresponds fairly
directly to some primitive function or construct, but a given VOP
also has a fairly predictable instruction sequence. An operation
(such as +) may have multiple implementations with different
cost and applicability. The choice of a particular VOP such as
+/fixnum or +/single-float represents this choice of
implementation. Once you are familiar with it, the VM
representation is probably the most useful for determining what
implementation has been used.
- An assembly listing, annotated with the VOP responsible for
generating the instructions. This listing is useful for figuring
out what a VOP does and how it is implemented in a particular
context, but its large size makes it more difficult to read.
- A disassembly of the generated code, which has all
pseudo-operations expanded out, but is not annotated with VOPs.
Note that trace file generation takes much space and time, since the trace file
is tens of times larger than the source file. To avoid huge confusing trace
files and much wasted time, it is best to separate the critical program portion
into its own file and then generate the trace file from this small file.
Next: 5.13 Efficiency Notes
Up: 5.12 General Efficiency Hints
Previous: 5.12.4 Mapping and Iteration
Raymond Toy
Mon Jul 14 09:11:27 EDT 1997