RAM cost of entering functions
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.