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?
Arduino Stack Exchange is a question and answer site for developers of open-source hardware and software that is compatible with Arduino. It only takes a minute to sign up.
Sign up to join this communityA 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?
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.
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:
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.