How can I optimize GCC compilation for memory usage?

I am developing a library that should use as little memory as possible (I am not worried about anything else like binary size or speed optimization).

Are there any GCC flags (or any other GCC related options) that I can use? Should I avoid some level of -O * optimization?

+3


source to share


3 answers


In your -or library, any code in idiomatic C- has several kinds of memory usage:

  • the size of the binary, and really -Os

    should optimize this
  • heap memory using dynamic C allocation , that is malloc

    ; You obviously need to know how and how much memory heaps are allocated (and then free

    -d). The actual memory consumption will depend on your specific implementation malloc

    (for example, many implementations where a call malloc(25)

    might actually consume 32 bytes) and not the compiler. By the way, you could design your library to use some memory pools, or even implement your own allocator (above OS system calls like mmap

    , or above malloc

    etc.)
  • local variables, that is , call frames on the call stack. It mostly depends on your code (but an optimizing compiler, for example, -Os

    or -O2

    for gcc

    will probably use more registers and maybe a little less stack when optimizing). You can pass -fstack-using in gcc

    order to ask to specify the size of each call frame, and you can len, to receive a warning when a call exceeds the frame len bytes. -Wstack-usage=

  • global or static variables. You should know how much memory they need (and you can use nm

    some other binutils program to query them). By the way, careful declaration of some variables inside the function static

    will reduce the stack consumption (but you cannot do this for every variable or every function).

Also note that in some limited cases GCC makes end calls and then the stack usage is reduced (since the caller's stack frame is reused in the called side). (See also this old question ).

You can also ask the compiler to package a specific one struct

(be careful, this can significantly reduce performance). You may want to use some types of attributes, such as __attribute__((packed))

, etc .... and perhaps also some variables attributes, and so on ....

Perhaps you should read more about garbage collection as GC methods, concepts, and terminology can make a difference. See this answer .



On Linux, the valgrind tool should be useful too ... (and in the debugging phase of -fsanitize=address

recent GCC).

Maybe you can also use some code generation options like -fstack-reuse=

either -fshort-enums

-fpack-struct

or -fpack-struct

or -fstack-limit-symbol=

or or -fsplit-stack

; be very careful: some of these options make your binary incompatible with your existing C libraries (and others!) (then you may need to recompile all libraries in use, including yours , with the same code generation flags). libc

You should probably enable link- time optimization by compiling and linking with-flto

(in addition to other optimization flags like -Os

).

You should definitely use the latest version of GCC . Please note that GCC 5.1 was released a few days ago (in April 2015).

If your library is large enough to be worth the effort, you might even consider tuning your GCC compiler with MELT (to help you learn how to spend less memory). This can take weeks or months of work.

+7


source


there are advantages to using "stack frames", but more stack space is used to store the stack frame pointer.

You can tell that the compiler doesn't use stack frames. This will (usually) slightly increase the size of the code, but reduce the amount of stack used.

you can only use char and shorten values, not int.

This is bad programming practice, but can reuse variables and arrays for multiple purposes.



if some set of variables are mutually exclusive in use, then you can put them in a union.

If the list of function parameters is very short, then for the compiler it is possible to pass all the parameters to registers. (with an architecture with a lot of general purpose registers it really helps here.

Use only one malloc that contains ALL the area required for malloc operations to minimize the amount of memory allocated.

there are many methods. Most make the code much harder to debug / maintain and often make the code much harder for people to read.

+3


source


Whenever possible, you can use -m32 to compile your application for 32-bit. Thus, the application will only consume half of the memory on 64-bit systems.

apt-get install libc6-dev-i386
gcc -m32 application.c -o application

      

+1


source







All Articles