CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 13 of 13
  1. #1
    Join Date
    Oct 2006
    Location
    Sweden
    Posts
    3,654

    [RESOLVED] Reduction of the flash footprint

    I'm currently involved in an embedded (cortex M3) C++ project where we're about to run out of flash.

    A quick check of the map file give that, in our case, the destructors consume about 10-15% of the available space. Since we're allocating all things that are needed at startup but never delete anything (both a requirement & also impossible due to the lack of a proper memory manager) the thought of getting rid of all destructors in the target build is appealing.

    I know that this question is somewhat crazy/desperate but is there a safe way of telling gcc not to emit any code for destructors? If so, can that be made in such a way that a linker error catch for instance mistakes such as creating an object on stack?
    Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are, by
    definition, not smart enough to debug it.
    - Brian W. Kernighan

    To enhance your chance's of getting an answer be sure to read
    http://www.codeguru.com/forum/announ...nouncementid=6
    and http://www.codeguru.com/forum/showthread.php?t=366302 before posting

    Refresh your memory on formatting tags here
    http://www.codeguru.com/forum/misc.php?do=bbcode

    Get your free MS compiler here
    https://visualstudio.microsoft.com/vs

  2. #2
    Join Date
    Nov 2003
    Posts
    1,902

    Re: Reduction of the flash footprint

    Some things that come to mind:
    Have a common base object with a virtual destructor that does nothing - then remove all other destructors. This should route all destrutor calls to the virtual base destructor.

    Tune your optimization settings to "reduce code size" - like turning off some inline expansions etc.

    Convert any static libraries (causing code duplication) into shared libraries.

    gg

  3. #3
    Join Date
    Oct 2006
    Location
    Sweden
    Posts
    3,654

    Re: Reduction of the flash footprint

    Thanks Codeplug.

    I tried -Os and that reduced the footprint about 10% so that might be a way if the resulting speed is enough. Some parts of the code is speed critical so one way might be to use different optimizations for different parts but I get a feeling that it would make the code harder to maintain.

    I also tried the trick to remove the implementation destructor, just leaving the interface destructor, but the implementation destructor was still emitted so I guess gcc make a default one.

    I did however test the of variant of having a non-virtual destructor in the interface and no destructor in the implementation and that make nothing being emitted! It will be somewhat annoying to always #ifdef them or similar (since we want them when unit testing in Windows) but it's still a possible solution. The bad thing is that a stack allocated object will not be detected but hopefully that is caught either in the reviews or by the unit tests (thinking something like disallowing destructors to run unless it's part of the test tear down).

    This is a all-in-one application running on a small single chip CPU (64k flash, 16k ram) so shared libraries isn't applicable but it's a good point for other situations.

    We'll, I think that we have to discuss what road to travel within the team. It always come down to the balance between work effort and the payback...
    Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are, by
    definition, not smart enough to debug it.
    - Brian W. Kernighan

    To enhance your chance's of getting an answer be sure to read
    http://www.codeguru.com/forum/announ...nouncementid=6
    and http://www.codeguru.com/forum/showthread.php?t=366302 before posting

    Refresh your memory on formatting tags here
    http://www.codeguru.com/forum/misc.php?do=bbcode

    Get your free MS compiler here
    https://visualstudio.microsoft.com/vs

  4. #4
    Join Date
    May 2001
    Location
    Germany
    Posts
    1,158

    Re: Reduction of the flash footprint

    Disabling exception handling (if/where possible) may save you another 8-10%.

  5. #5
    Join Date
    Oct 2006
    Location
    Sweden
    Posts
    3,654

    Re: Reduction of the flash footprint

    Yes, neither exception handling nor RTTI are enabled. Enabling that completely overflows the flash. If I remember correctly that added 40-50k or so.
    Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are, by
    definition, not smart enough to debug it.
    - Brian W. Kernighan

    To enhance your chance's of getting an answer be sure to read
    http://www.codeguru.com/forum/announ...nouncementid=6
    and http://www.codeguru.com/forum/showthread.php?t=366302 before posting

    Refresh your memory on formatting tags here
    http://www.codeguru.com/forum/misc.php?do=bbcode

    Get your free MS compiler here
    https://visualstudio.microsoft.com/vs

  6. #6
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Reduction of the flash footprint

    destructors tend to be necessary. removing these 'automatically' could cause a lot of pain. If the destructors take space, and you don't need the code in the destructors... Why have code in the destructors at all ?

    some suggestions are already given, here's my shortlist...
    - compile for size instead of performance. With todays processors, there is advantage in small code as well afterall.
    - replace complex/large calculations with static data (works well if you have large functions that are only ever called with a limited amount of different parameter values).
    - the other way around... replace large precalculated data tables by calculation functions. (if feasible, this'll add to running time).
    - reduce data types. use BYTE where you don't need an DWORD etc. note that on some platforms, some datatypes are inefficient and cause performance and/or code size issues. on windows, 2byte types are inefficient. each instruction accessing them causes an extra data-size prefix byte which can run up. The prefix also stalls the CPU pipeline.
    - avoid 'monolithic' does-everything-for-you generalised functions like sprintf/prints. These tend to take a LOT of code space to handle all the different types of formatting. For the same reason the C++ stream classes could be a bad thing. Although when well implemented it'll only add in what you need. You can fairly easily replace a generic sprintf() with a custom string formatting function that has only the features you need and is on a fraction in size.
    There are other 'big' things in C/C++ like regex that can be replaced with simpler pattern matching tech.
    - if feasible, use innate OS support rather than library alternatives. Extending the above, assuming it's windows, you could replace the sprintf() library call with the wnsprintf() windows API call (Shlwapi.dll), there's a ton of other library replacements in that dll.
    - if you are using floating point types. Try removing it entirely or replacing it with basic fixed point math. Including FPU support takes quite a bit of space in the runtime (also one reason why sprintf() is bad, because it drags in FPU support).
    - make sure you pool identical static strings
    - replace complex/elaborate parsing code with simpler state machines (hand made, or formalize the syntax then lex/yacc).

    there's lots of other stuff you can do, but without knowing more about what it is, it's a bit of a wild goose chase

  7. #7
    Join Date
    Oct 2006
    Location
    Sweden
    Posts
    3,654

    Re: Reduction of the flash footprint

    Even though we don't need the destructors for the current target we want the code to be well behaved if/when re-used on other systems.

    Thanks for the response but for this issue I think we live in quite different worlds. I saw your post about build time, 470 Mb in static arrays... we have 64 kb flash (well almost 64 since there's also a bootloader).
    Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are, by
    definition, not smart enough to debug it.
    - Brian W. Kernighan

    To enhance your chance's of getting an answer be sure to read
    http://www.codeguru.com/forum/announ...nouncementid=6
    and http://www.codeguru.com/forum/showthread.php?t=366302 before posting

    Refresh your memory on formatting tags here
    http://www.codeguru.com/forum/misc.php?do=bbcode

    Get your free MS compiler here
    https://visualstudio.microsoft.com/vs

  8. #8
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Reduction of the flash footprint

    Quote Originally Posted by S_M_A View Post
    Even though we don't need the destructors for the current target we want the code to be well behaved if/when re-used on other systems.

    Thanks for the response but for this issue I think we live in quite different worlds. I saw your post about build time, 470 Mb in static arrays... we have 64 kb flash (well almost 64 since there's also a bootloader).
    just because some of our projects are huge, doesn't mean they're all that way. :-)

    We also have embedded stuff that has very tight restrictions, even smaller than 64K (which depending on the platform can be 'huge').
    Even that 470 Mb static array is an example. Without those tables, the actual calculation code wouldn't even fit in a Win32 program, and be considerably slower as well.

    The tricks listed in and by themselves all work depending on the platform. One I even forgot to mention is removing the C-runtime entirely, means you can't use any of the default headers anymore, and you'll need to do some of your own bootstrapping (because constructors/destructors of global instances won't be called anymore). But it can make a big different in size.

    For VS at least, removing the runtime means you can make a basic "hello world" Windows app that's a 4k exe. With the runtime it'll be around 40K+. Your mileage here may vary depending on what platform you're building for and how big the runtime is.

  9. #9
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Reduction of the flash footprint

    if you want the destructors to not be there... There's afaik only 2 ways to do that.

    1) remove the runtime (as indicated above). Only call the constructors. With nobody calling the destructors (which normally the runtime will take care off), they should end up being trimmed out in the linker assuming the linker's doing that.

    2) #if/#endif around your destructors and don't have them be there when building for the flash image.

  10. #10
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Reduction of the flash footprint

    another way is to use the clang compiler instead of gcc; then, use the llvm api to write an ad hoc optimization module ( working either on the c++ AST or on the IR code ) to strip destructors ( even on a per class basis, or based on more complex (but still high level) scenarios ); yes, there's a steep learning curve compared to out of the box solutions, but, in this way you can continue writing standard code as usual; moreover, AFAIK the llvm api is stable and well written, so you can relatively easily componentize your optimization passes ( of arbitrary complexity ) on a per-platform basis. IMO such an approach would pay off in the long run ...

    the only dilemma I'd have is, are you really sure you can't accomplish the same result with standard c++ ?

  11. #11
    Join Date
    Oct 2006
    Location
    Sweden
    Posts
    3,654

    Re: Reduction of the flash footprint

    Wow, yes that would be the ultimate solution but also require quite much extra work.

    Anyway, things have changed a bit. Now it's highly likely that the current cpu will be replaced with one with a bigger flash (same family so no code changes at all).
    Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are, by
    definition, not smart enough to debug it.
    - Brian W. Kernighan

    To enhance your chance's of getting an answer be sure to read
    http://www.codeguru.com/forum/announ...nouncementid=6
    and http://www.codeguru.com/forum/showthread.php?t=366302 before posting

    Refresh your memory on formatting tags here
    http://www.codeguru.com/forum/misc.php?do=bbcode

    Get your free MS compiler here
    https://visualstudio.microsoft.com/vs

  12. #12
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Reduction of the flash footprint

    Quote Originally Posted by S_M_A View Post
    Wow, yes that would be the ultimate solution but also require quite much extra work.
    not necessarily, in this specific case it's probably quite easy;

    just for fun, if we compile the snippet

    Code:
    // compile with: clang -S -emit-llvm test.cpp
    
    #include<iostream>
    struct A{~A(){ std::cout << "hallo"; }} a;
    struct B{~B(){ std::cout << "world\n"; }} b;
    int main(){}
    the resulting IR code ( FYI, the intermidiate asm-like language used by lvmm ) gives for each global ( including those implicitly pulled in by <iostream> )

    Code:
    ...
    define internal void @__cxx_global_var_init1() section "__TEXT,__StaticInit,regular,pure_instructions" {
      %1 = call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @a, i32 0, i32 0), i8* @__dso_handle) #1
      ret void
    }
    ...
    so, in order to strip destructors it's probably just a matter of removing all those __cxa_atexit calls. So, the "optimization" process may consist just in running a proper sed command ( yes, I have no idea what in the above is guaranteed or not, but it cannot be much harder than this I suppose ... ).

  13. #13
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Reduction of the flash footprint

    Quote Originally Posted by S_M_A View Post
    Anyway, things have changed a bit. Now it's highly likely that the current cpu will be replaced with one with a bigger flash (same family so no code changes at all).
    If you're doing the change to a diff CPU "anyway" or for reasons unrelated to the flash size memory issue you have now, then "ok", by all means benefit from the upgrade.

    If the issues are what promted the change, then that could be a big issue (price, power needs, ...) depending on how many of those devices you intend to ship. If the enw chip is plug replaceable then it's easy, but if it needs a hardware redesign than that could be problematic.



    A few years ago we were hired to handle exactly this sort of problem. New required changes to the firmware were just a fraction to big to fit on the CPU, and we were hired to "make it fit" after their own devs had failed to reduce the footprint any further.
    Upgrading the chip was technically possible, but would mean a more expensive chip (costing 2 eurocent per unit more), as well as needing more power thus reducing battery life.

    We went way beyond the requirements on that (fairly easily once we established the real problem area) instead of reducing the 53K image to 48K, we reduced it to just below 32K. So they could actually go down on the chip spec (reducing cost by 1 eurocent per unit) and as a consequence increase battery life by about 15%.

    15% more battery life is significant, and while 1 eurocent per unit may seem 'ridicilous' we are talking about a device that gets produced in the "several millions per year" type quantity. so 1 eurocent is significant too.

    Going to assembly (basically the big reason why we were hired) would have reduced the size even more, but that was a futile exercise since there was no smaller chipmodel to consider. The company was pleasantly surprised to find out that we reduced the footprint this much and still keep all the code as plain C, and make minimal changes to their own codebase.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured