I've been working on a data field for a while, and one of the hardest things to deal with is code size, especially if you want your code to work on devices like the fr235, which only allows 16k for data fields.
Some of my observations:
- consts and enums have code size cost, even if you don't use them (i.e just declaring an enum will reduce the memory available).
- Using consts and enums generates more code than using the corresponding constants directly - especially if you follow the lead of the garmin samples and fully qualify their names (ie $.Foo.Bar.Baz, when Bar.Baz would have pinned it down). Fully qualifying probably reduces the runtime overhead, but it definitely generates more code.
- The monkeyc compiler doesn't do constant folding at all. So
const FOO = 1+1;
generates more code thanconst FOO = 2;
- Initializing arrays, especially if you initialize them with named constants, can take a lot of code. eg an array of heart-rate-zone colors
[Graphics.COLOR_LT_GREY, Graphics.COLOR_BLUE, Graphics.COLOR_GREEN, Graphics.COLOR_YELLOW, Graphics.COLOR_RED]
takes hundreds of bytes. If you can get away with 6 bit colors (for this particular array that's not a problem, and no mip device needs more than 6 bit color) you can pack 5 6-bit words into a Number, and then extract them on the fly. Even though the extraction code is a little complex, doing so saved me more than 350 bytes in this case
The downside of trying to work around all the above is that now your code is littered with meaningless numbers. So I started looking at a preprocessing step so I could keep the consts and enums, but get the benefits of using the literals directly. An add hoc regex based approach shaved 300 bytes off my data field, but I could see there were more wins to be had - eg constant folding after substituting in values could save more code; removing unused enums (including enums that *became* unused as a result of the preprocessing step) could save more.
I'd recently written a monkey-c code formatter, as a plugin for Prettier, so I could use that to produce an AST, modify the AST, and then use Prettier to print out the resulting code, and then build that. The result is the latest version of Prettier-extension-monkeyc. Using that takes about 1k off my data field's peak memory, which is *huge* for a 16k data field.
The extension is pretty much plug-and-play. Install it, and you get new commands in the command palette. "Prettier Monkey C: Build and Run Optimized Project", and "Prettier Monkey C: Export Optimized Project" are probably the most useful commands. If you just want to look at the code changes, "Prettier Monkey C: Generate Optimized Project" will just generate the optimized sources in bin/optimized for you to inspect.
Currently, barrels are not supported, but anything else that doesn't work is a bug.
I'd appreciate any feedback!