I'm in the home stretch on a large project involving radio remote control and speech among other things, and found that my sketch won't fit in 32k anymore, so I set about seeing what I could do to optimize it. Either I'm doing something very wrong, or the compiler is. I'm hoping that someone with more experience with large projects can shed some insight on my experiences.
First off, I use serial to debug, a lot. This eats up sram of course, and will bring an ardweeny to its knees pretty fast. So I do my development on a mega, and then turn off the debug code, and it will then run fine on a smaller proc. I'm turning the debugs on and off with #define switches, to exclude use of Serial. This has the double effect of keeping the Serial library off the flash as well as shedding a ton of string literals. I've ran into the ironic situation that turning OFF the debug is yielding a larger build. As in, ALL references to Serial are removed via a main #define being commented out.
Your knee-jerk reaction may be 'post the code', but most of you probably don't actually want that. My main sketch is nothing but 15 includes, and some of those are 20 pages long. It compiles to over 46k. In my reductions for testing, here's a "compile size sensitive" function:
// add a word to the message. provide duration in tens of ms
void AddWord(uint8_t got_word_id) {
message_word_id[message_wordcount] = got_word_id;
message_wordcount = min(message_wordcount+1,message_max);
//booya
// Serial.print(":AddWord/"); // 4.5 KB gets ADDED to the sketch if this line is commented!
}
I spent two hours with a machete, hacking things down to try to produce a small reproducible issue, but the flood gradually drops down to a trickle as I cut things away, so I stopped trimming off the top and went into the bowels to find the offender in a commonly-called area. The above function gets called A LOT. The commenting of those three lines (Serial, and the two message_) produces such counter-intuitive results that it's difficult to believe.
2292: all three commented
3162: serial and one message commented
5082: two messages commented
5108: one message commented (small difference which one)
9842: serial commented
So strangely, the worst configuration is with the serial command commented OUT! (and that is THE only serial command left in the entire sketch) And, look at the incredible sketch savings for commenting out ONE of the message commands. In that respect, it's as though the compiler isn't calling the function, but is instead replacing each of the function calls with the copies of the function's code. (add one line to the function, compiler adds 200 copies of the line to your sketch! yikes!)
So I'm somewhat at a loss for words as to how to "beat the compiler at its own game" of code optimizing. Doing things that seem to make sense, (consolidating frequently used code into a called function, and removing unnecessary code and libraries: serial) have the exact opposite of the expected effects. Does anyone understand the "method to the madness"?