Features! Speed! Reliability! The buzz-words of the modern era of
software development. Every computer programmer is trained that the
best program is one that does more than the competition, faster, and
with fewer bugs. However, the embedded market is a bit different than
the average college graduate realizes.
Memory seems like a cheap commodity, but when you're building ten
million units, saving small amounts (even
$0.05) each may be important. With inexpensive items, the cost
of an extra processor (or one with
more memory) maybe be the difference between a profit margin and
bankruptcy.
Suddenly size matters a whole lot! Limiting memory requirements is
often an essential part of embedded projects, and this article will
discuss how to cut programs down to size through efficient use of a
compiler.
There are many ways to shrink a program's footprint, but some are
pretty impractical. For instance, removing features may disappoint the
product's audience. Starting over and trying again with a new design
doesn't really help time-to-market.
Hand-optimizing thousands of lines of assembly code is a trying task
best left to the experts. Crossing your fingers and hoping never works.
So what should you do to reduce your memory requirements?
Start with the basics.
Compilers Are The Experts
When you write in a high level programming language, you shouldn't have
to think about what the machine code will look like. That's not your
job. Optimizing compilers have been around for decades, and they keep
getting better. (That's my job!)
Compilers are chock-full of general purpose optimizations which will
optimize most code you throw at them. In fact, because compilers are
written for and tested on mainstream benchmarks and real user code, the
easiest way to get small code from an optimizing compiler is not by
being clever - it's by writing straight-forward code.
(A small tip: The more your
program looks like the code your compiler and its authors have seen
before, the better the compiler will do. Following common language
paradigms is probably the best way to get good results... and it'll
make your code easier to understand and enhance/debug later on!)
Once you accept that compilers are a trustworthy tool to help you
get the results that you need, there's still a big question: which
compiler should you use? There are several viable options, and deciding
which is right for you may require some research.
Look up the results of compilers on standard benchmarks (e.g. SPEC, EEMBC, and Dhrystone) to get a general idea of
rankings, and when possible try an evaluation copy of various compilers
to see how well they perform on your code base.
Compiler results tend to generalize, so the compilers which do the
best on code you already have will usually do the best on code which
you write in the future.
Now, numbers do not lie, but sometimes they don't say enough.
Optimizations from the best compilers are typically within 10-20% of
the competitions' in terms of code size plus most compilers share a
large set of standard optimizations (although implementations vary).
However, there are major differentiating features.
(Tip: High-impact optimizations
are often not enabled by default, but they can greatly improve your
product's code size. Turn them on...assuming your compiler supports
them!)