2

A friend has told me I shouldn't rely on functions because, during execution, they occupy a significant amount of RAM.

Is that true or, if it isn't, what's the maximum suggested level of function nesting at runtime?

1
2

A friend has told me I shouldn't rely on functions because, during execution, they occupy a significant amount of RAM.

I wouldn't say "significant", but some RAM is used, yes.

Every time a function is called any registers used in the execution of that function are placed onto the stack. Also some parameters to the function may be passed on the stack (depending on the ABI for the architecture you're using). Further, any local variables used inside the function also go on the stack.

These are only temporary allocations and are released again when the function exits.

Depending on your program the "call stack" can be insignificant compared to the local variables.

what's the maximum suggested level of function nesting at runtime?

Low enough that you don't run out of memory. When you have plenty of memory then your call stack is irrelevant. When you only have a couple of hundred bytes, or a hardware stack (like on the low-end PIC microcontrollers) with a limited depth, then keeping your program flatter can be better.

The main reason for flattening a program is usually for execution speed rather than for memory use.

1
  • 2
    Also, if a function is only called in one location, or is very short, the compiler will try to inline the function, negating the "cost" associated of the function call.
    – Gerben
    Dec 17 '20 at 17:18
2

I guess avoiding functions may have been relevant with dumb compilers, a few decades ago. Compilers today are pretty good at optimizing and, since recently, the Arduino environment enables “link time optimization”. This means the optimizer can see the whole program at once, which enables:

  • function inlining across compilation units (and the optimizer does this pretty aggressively)
  • saving, in the function prologue, only the registers that really need to be saved.

In most cases, the “optimal” size for a function is whatever size optimizes the readability of the code. In the rare cases where you would need to merge a function into its callers for performance purposes, you can qualify the function as

inline __attribute__((always_inline))

But this only makes sense after you disassembled the program and noticed the compiler did not make the right optimization choices. A quite infrequent situation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.