5.1.5 Writing Efficient Code
Writing efficient code that works is a complex and prolonged process.
It is important not to get so involved in the pursuit of efficiency
that you lose sight of what the original problem demands. Remember
that:
- The program should be correct—it doesn’t matter how
quickly you get the wrong answer.
- Both the programmer and the user will make errors, so the
program must be robust—it must detect errors in a way that
allows easy correction.
- A small portion of the program will consume most of the
resources, with the bulk of the code being virtually irrelevant to
efficiency considerations. Even experienced programmers familiar
with the problem area cannot reliably predict where these “hot
spots” will be.
The best way to get efficient code that is still worth using, is to separate
coding from tuning. During coding, you should:
- Use a coding style that aids correctness and robustness without
being incompatible with efficiency.
- Choose appropriate data structures that allow efficient
algorithms and object representations
(see object-representation). Try to make interfaces abstract
enough so that you can change to a different representation if
profiling reveals a need.
- Whenever you make an assumption about a function argument or
global data structure, add consistency assertions, either with type
declarations or explicit uses of
assert
, ecase
, etc.
During tuning, you should:
- Identify the hot spots in the program through profiling (section
profiling.)
- Identify inefficient constructs in the hot spot with efficiency
notes, more profiling, or manual inspection of the source. See
sections general-efficiency and efficiency-notes.
- Add declarations and consider the application of optimizations.
See sections local-call, inline-expansion and
non-descriptor.
- If all else fails, consider algorithm or data structure changes.
If you did a good job coding, changes will be easy to introduce.