What are some best practices for reducing memory usage in C?

23,003

Solution 1

In C, at a much simpler level, consider the following;

  • Use #pragma pack(1) to byte align your structures
  • Use unions where a structure can contain different types of data
  • Use bit fields rather than ints to store flags and small integers
  • Avoid using fixed length character arrays to store strings, implement a string pool and use pointers.
  • Where storing references to an enumerated string list, e.g. font name, store an index into the list rather than the string
  • When using dynamic memory allocation, compute the number of elements required in advance to avoid reallocs.

Solution 2

A few suggestions that I've found useful in working with embedded systems:

  • Ensure any lookup tables or other constant data are actually declared using const. If const is used then the data can be stored in read-only (e.g, flash or EEPROM) memory, otherwise the data has to be copied to RAM at start-up, and this takes up both flash and RAM space. Set the linker options so that it generates a map file, and study this file to see exactly where your data is being allocated in the memory map.

  • Make sure you're using all the memory regions available to you. For example, microcontrollers often have onboard memory that you can make use of (which may also be faster to access than external RAM). You should be able to control the memory regions to which code and data are allocated using compiler and linker option settings.

  • To reduce code size, check your compiler's optimisation settings. Most compilers have switches to optimise for speed or code size. It can be worth experimenting with these options to see whether the size of the compiled code can be reduced. And obviously, eliminate duplicate code wherever possible.

  • Check how much stack memory your system needs and adjust the linker memory allocation accordingly (see the answers to this question). To reduce stack usage, avoid placing large data structures on the stack (for whatever value of "large" is relevant to you).

Solution 3

Make sure you're using fixed point / integer math wherever possible. Lots of developers use floating-point math (along with the sluggish performance and large libraries & memory usage) when simple scaled integer math will suffice.

Solution 4

All good recommendations. Here are some design approaches that I've found useful.

  • Byte Coding

Write an interpreter for a special-purpose byte-code instruction set, and write as much of the program as possible in that instruction set. If certain operations require high performance, make them native-code and call them from the interpreter.

  • Code Generation

If part of the input data changes very infrequently, you could have an external code generator that creates an ad-hoc program. That will be smaller than a more general program, as well as running faster and not having to allocate storage for the seldom-changing input.

  • Be a data-hater

Be willing to waste lots of cycles if it will let you store absolutely minimum data structure. Usually you will find that performance suffers very little.

Solution 5

Avoid memory fragmentation by using your own memory allocator (or carefully using the system's allocator).

One method is to use a 'slab allocator' (see this article for example) and multiple pools of memory for objects of different sizes.

Share:
23,003

Related videos on Youtube

user27424
Author by

user27424

Updated on April 08, 2021

Comments

  • user27424
    user27424 about 3 years

    What are some best practice for "Memory Efficient C programming". Mostly for embedded/mobile device what should be the guidelines for having low memory consumptions ?

    I guess there should be separate guideline for a) code memory b) data memory

    • SmacL
      SmacL over 15 years
      Nice to see such a variety of quite different good answers rather than repitions.
    • Sebastian Mach
      Sebastian Mach about 10 years
      Let me refine your title. "memory efficient" could also mean read and/or write speed.
  • strager
    strager over 15 years
    For complicated algoriths, ARM mode may reduce code size. For simple operations, THUMB mode may be better. It all depends on the context, really. But for general code, I agree that THUMB is smaller than ARM.
  • SmacL
    SmacL over 15 years
    Pre-allocating works well for speed and size of certain applications. For others, it can worsen size requirements, as the app cannot typically re-use memory across modules.
  • strager
    strager over 15 years
    Ah, completely forgot about the first three points myself. I thought it was too obvious and overlooked it. xD
  • strager
    strager over 15 years
    This assumes the system lacks an FPU, and floating-point operations need to be emulated. Still, floats and doubles take more memory than fixed-point integers in most cases, so it does help to use the latter.
  • SmacL
    SmacL over 15 years
    +1 for avoid DOM. This is even true on desktop apps with large serialized data.
  • SmacL
    SmacL over 15 years
    Yep. The above answer was added after having read yours,nimrodms & monjardins, and was there to add all the more obvious ommissions.
  • Mikeage
    Mikeage about 15 years
    1. That may come with a speed penalty. Better: structure your structs intelligently: struct s { int i; char c; } instead of struct s {char c; int i;} 2. Unions are very good. 3. bitfields can be painfully slow. Beware
  • SmacL
    SmacL about 15 years
    @Mikeage - Yup, I find that typically you are either optimizing for either memory or speed, where the two are in opposition.
  • JBRWilkinson
    JBRWilkinson over 11 years
    +1. This was a winning factor when we needed to get a full HTML 4 browser working in 8mb of RAM.
  • phuclv
    phuclv about 10 years
    most embedded systems have instructions for bit operations, so bitfield is a good choice
  • Someone
    Someone over 3 years
    How to use bit fields?
  • Someone
    Someone over 3 years
    What do you mean by "cycles" in this case?
  • Someone
    Someone over 3 years
    wow… how!? 8mb is TINY by modern standards!
  • Mike Dunlavey
    Mike Dunlavey over 3 years
    @Someone: Machine cycles, instruction cycles, the little steps that machines do that take time. If you've got a 1-gigahertz machine, each instruction takes a number of cycles, like maybe 10 on average. So a program that takes 100 million instructions will take 1 billion cycles, which is one second. That sounds like a big number, but in typical modern software it's not big at all.