C Inline Functions and Memory Use - c

If I use inline functions, does the memory usage increase?

There are two kinds of memory usage that inline functions will affect:
code size — in general, inlining code will increase how much memory is used to load your program. This is because there will be multiple copies of the generated code scattered around your program. However, this isn't always true -- if your inlined function was only used once, there's little change, and if the inlined function is very small, you could get a net reduction in code size by removing the function call overhead. Also, the function may be reduced in size by the optimizer that's able to remove code that's not used in the particular inline invocation.
stack usage — If your inlined functions have lots of local variables, then you may use more stack space. In C, the compiler usually allocates the stack space for a function once upon entry to the function. This has to be large enough to hold all the local variables that aren't stored in registers. If you call a function out-of-line, the stack for that function is used until it returns, when it's released again. If you inline the function, then that stack space will remain used for the whole life of the uber-function.
Inlining won't affect heap usage, as the same allocations and deallocations would occur for the inlined code as would occur for the non-inlined version.

There is another point you have to consider:
Using inline functions, the compiler is able to see where variables of the caller are going to be used as variables in the callee. The compiler can optimize out (often this is really many assembler lines that can be omitted. look out for the so called "aliasing problem") redundant code based on that knowledge. So your "code bloat" is often not all that big, especially if you have smaller functions it can even reduce bloat as Jim stated above.
Someone made a good point: Better make the compiler decide whether it inlines the function in question or not, since it knows the code it generates better than you ever would.

Depends on the function. Simple one-liners could have a memory reduction since no callstack needs to be setup and cleaned and no function call is made. If the function is larger than this overhead needed to call a function, then it will of course bloat the code.

That is really un-answerable in the general case.
To start with you do not generally have control over the in-lining. Even if you mark a function inline it is actually still up to the compiler wither it will actually do the in-lining (it is just a hint).
The compiler will do its best to optimize the code; using in-lining is just one tool in doing this. So inlining short functions will make the code smaller (as you don't need to set up the parameters for the call or retrieve the return value. But even with long functions the answer is not absolute.
If the compiler decides to inline a long function then you would think the code would get longer. But this is not generally the case; as this gives the compiler extra opportunities to apply other optimization techniques that could potentially make the code still smaller. If the compilers analysis finds that the resulting code bloat is detrimental to the code the in-lining will not be done.
Basically the compiler does its analysis and decides and the best course of action.
Conclusion. Don't worry about it. The compiler is smarter than you and will do the correct thing.

Inline functions definitely increase the size of your final executable(or binary), because they will be "copy-pasted" whereever you call them.

You program will in the general case become larger (I'm sure there are exceptions, though). The runtime memory consumption might go down, but not by much.
Why are you asking? Normally, you let the compiler determine whether a function should be inlined or not; it can usually make a better call given the size and complexity of the function.

A function call requires several processor instructions.
You usually need a PUSH instruction for every argument to the function, a CALL instruction to call the function, and often another instruction that cleans up the stack after the function call.
Also, functions may modify the processor's registers, so the calling function may need more instructions to preserve registers or reload values that would otherwise still be in registers.
So if the function you're calling is just a few instructions long, inlining it can save memory and run faster.
That said, inlining is for when your profiler tells you that you should.

It sometimes so happens that we have functions scattered all over the program.In this case a function call causes the program to jumps to the address of the function and come back when the function call terminates. This takes away some precious time.
The above problem can be resolved with the use of inline functions. This causes the compiler to call the code directly from the source. No new memory instruction set is created for the inline function code.
Although the inline declaration in c++ is free and occurs automatically when the function is defined in the declaration, in c it is restricted by the following rules ::
In C, any function with internal linkage can be declared inline, but a function with external linkage is has restrictions on inline.
If the inline keyword is used in the function declaration, then the function definition should be present in the same translation unit.
inline datatype function_name(arguments)
This code runs upto 30% fastert than a non inline function, the rest depending on the prcessor speed.
Now comes the strategy part. You may use inline functions at your will but keeping in mind that inline functions can take much less time to execute but they have a high memory occupancy on the run. Also the compiler has always an option to overlook your inline declaration if the code declared inline is abnormally large compared to the code size.
Inline declaration although destroys the order of evaluation, does not make the function internal. The function is still external.

Related

Why is optimizing inline functions easier than normal functions?

Im reading What Every Programmer Should Know About Memory
https://people.freebsd.org/~lstewart/articles/cpumemory.pdf and it says that inline functions make your code more optimizable
for example:
Inlining of functions, in particular, allows the compiler to optimize larger chunks of code at a time which, in turn, enables the generation of machine code which better exploits the processor’s pipeline architecture
and:
The handling of both code and data (through dead code elimination or value range propagation, and others) works better when larger parts of the program can be considered as a single unit.
and this also:
If a function is only called once it might as well be inlined. This gives the compiler the opportunity to perform more optimizations (like value range propagation, which might significantly improve the code).
After reading these, to me atleast it seems like inline functions are easier to optimize, but why? Why is it easier to optimize something is inline?
The reason that it is easier to make a better job when optimizing inlined functions than with outlined is that you know the complete context in which the function is called and can use this information to tune the generated code to match this exact context. This often allows more efficient code for the inlined copy of the function but also for the calling function. The caller and the callee can be optimized to fit each other in a way that is not possible for outlined functions.
There is no difference!
All functions are subject to being inlined by gcc in -O3 optimization mode, whether declared inline, static, neither or both.
see: https://stackoverflow.com/a/40783656/9925764
or here is the modifying the example of #Eugene Sh. without noinline option.
https://godbolt.org/z/arPEf7rd4

Functions splitting effect on running time

I am writing a DSP code in C (windows environment). The code should be modified, by another engineer, to run on Cortex-M4. This engineer claims that, for reduction of running time, many of the functions that I have implemented should be united into one function. I prefer to avoid it keeping clarity and testing.
Does his claim make sense? If it is, where I can read about it. Otherwise, can I show that he is wrong without a comparison of running time?
Does his claim make sense?
Depends on context. Modern compilers are perfectly able to inline function calls, but that usually means that those functions must be placed in the same translation unit (essentially the same .c file).
If your functions are in the same .c file then their claim is wrong, if you have the functions scattered across multiple files, then their claim is likely correct.
If it is, where I can read about it.
Function inlining has been around for some 30 years. C even added an inline keyword for it in year 1999 (C++ had one earlier still), though during the 2000s compilers turned smarter than programmers in terms of determining when and what to inline. Nowadays when using modern compilers, inline is mostly considered obsolete.
Otherwise, can I show that he is wrong without a comparison of running time?
By disassembling the optimized code and see if there are any function calls or not. Still, function calls are relatively cheap on Cortex M (unless there's a ton of different parameters), so doing manual optimization to remove them would be very tiny optimization.
As always there's a choice between code size and execution speed.
If you wish to remove the stack overhead of calling a new function but wish to keep your code modular then consider using the inline function attribute suitable for your compiler e.g.
static inline void com_ClearMessageBuffer(uint8_t* pBuffer, uint32_t length)
{
NRF_LOG_DEBUG("com_ClearMessageBuffer");
memset(pBuffer, 0, length);
}
Then at compile time your inline function code will be inserted into the code flow wherever it is called.
This will speed execution, but when called multiple times increase the code size.

Effect of removal "static" keyword for function

Recently, I have learned the existence of "backtrace" function.
This function allow one to retrieve, at some conditions, the callstack of an ELF running program compiled without debugging information.
It's perfect for me (I can't insert debugging symbol in production program), but for "backtrace" to work, there is (roughly) two condition :
Tell the linker to add extra information (by passing -rdynamic option).
Convert all "static" function to "non-static" function.
My worries is that if I fullfill this two condition, my program will be slower (because compiler can't optimise non-static function as he optimize static function ?).
As far as I know, adding extra information with -rdynamic doesn't impact program's performance : it's just add a little weight to the ELF binary.
So here's my question :
What is the effect in term of running performance when all static function become non-static function ?
Yes, your worries are correct: Declaring a function as static provides a good hint to the compiler, which it can turn into better optimization. The amount of speedup that you receive from static depends on your precise situation, though, so there's only truth in measurement (as always when it comes to performance).
The point about declaring a function as static is, that the compiler knows definitely, that it sees all the calling sites of a function. And if it sees, that the function is only called from one single place, it will generally always inline it, no matter how long it is. And the inlining may unlock further opportunities for optimization. This avoids the function call overhead, both in terms of size and speed. In this, static is actually a stronger hint than inline.
Of course, the effect on the performance depends on the frequency of calls to the static function. So, as I said, you need measurement to assess how much performance you gain from the static keyword.
What is the effect in term of running performance when all static function become non-static function ?
The answer is "some", I think. The only way you can be sure what the performance issue is likely to be is to measure the performance of your program with and without static functions. The most obvious thing I can think of is that the optimiser might not be able to inline non static functions.
You actually don't need to make the static functions non static, the only issue will be the lack of symbolic names in the backtrace.
However, I think you have bigger problems. From your link to the man page:
Omission of the frame pointers (as implied by any of gcc(1)'s nonzero optimization levels) may cause these assumptions to be violated.
For backstrace to work reliably, it looks like you will have to compile without optimisation. That will certainly have a huge impact on performance. I think I'd manage without it.
What is the effect in term of running performance when all static function become non-static function ?
Ans - None
A Static function means that function is only visible to that file only and cannot be called outside that file. i.e. it has file scope.
Static functions are typically used in large programs when you do not want your functions to clash with other people's functions. A static function ensures that you can define a function and use it inside your own file, and somebody else can also define the same static function name in other file.
If your code compiles after removing the static keyword, then you do not have two functions with the same name and it will work just like any normal function.
It will have no run time penalty.

Is there, as in JavaScript, a performance penalty for creating functions in C?

In JavaScript, there are, often, huge performance penalties for writing functions. For example, if you use this function:
function double(x){ return x*2; }
inside an inner loop, you are probably hitting your performance considerably, so it is really profitable to inline that kind of function for intensive applications. Does this, in general, hold for C? Am I free to create those kind of functions for everything, and rest assured the compiler will do the job, or is hand inlining still important?
The answer is: it depends.
I'm currently using MSVC compiler and GCC for a project at work and my experience is that they both do a pretty good job. Furthermore, the cost of a function call in native code can be pretty small, especially in functions that do not need to be accessible outside the executable (like functions not exported in a shared library). For these functions, there is more flexibility with how the call is actually implemented.
A few things to note: it's much easier for a compiler to optimize calls to static functions. Functions with external linkage often require link time optimization since one must know how and where the function is actually called, as well as the implementation, to do much optimization or inlining. This requires examining more than one compilation unit at a time.
I would say that you should use functions where it makes sense and makes the code easier to read and maintain. In general, it is safe to assume that the cost is smaller than it would be in JavaScript. But in the end, you'd have to profile the code to say anything more precise.
UPDATE: I want to emphasize that functions can be inlined across compilation units, but this requires link-time optimization (or whole program optimization). This is supported in both GCC (https://gcc.gnu.org/wiki/LinkTimeOptimization) and MSVC (http://msdn.microsoft.com/en-us/library/0zza0de8.aspx).
These days, if you can beat the compiler by copying the body of a function and pasting it everywhere you call that function, you probably need a different compiler.
In general, with optimizations turned on, gcc will tend to inline short functions provided that they are defined in the same compilation unit that they are called in.
Moreover, if the calling function and called function are in different compilation units, the compiler does not have a chance to inline them regardless of what you request.
So, if you want to maximize the chance of the compiler optimizing away a function call (without manually inlining), you should define the function call in .h file or in the same c file that it is called in.
There are no inner functions in C. Dot. So the rest of your question is kind of irrelevant.
Anyway, as of "normal" functions in C compiler may or may not inline them ( replace function invocation by its body ). If you compile your code with "optimize for size" it may decide to do not do inlining for obvious reason.

Difference between macros and functions in C in relation to instruction memory and speed

To my understanding the difference between a macro and a function is, that a macro-call will be replaced by the instruction in the definition, and a function does the whole push, branch and pop -thing. Is this right, or have I understand something wrong?
Additionally, if this is right, it would mean, that macros would take more space, but would be faster (because of the lack of the push, branch and pop instructions), wouldn't it?
What you are wrote about the performance implications is correct if the C compiler is not optimizing. But optimizing compilers can inline functions just as if they were macros, so an inlined function call runs at the same speed as a macro, and there is no pushing/popping overhead. To trigger inlining, enable optimization in your compiler settings (e.g. gcc -O2), and put your functions to the .h file as static inline.
Please note that sometimes inlining/macros is faster, sometimes a real function call is faster, depending on the code and the compiler. If the function body is very short (and most of it will be optimized away), usually inlining is faster than a function call.
Another important difference that macros can take arguments of different types, and the macro definition can make sense for multiple types (but the compiler won't do type checking for you, so you may get undesired behavior or a cryptic error message if you use a macro with the wrong argument type). This polymorphism is hard to mimic with functions in C (but easy in C++ with function overloading and function templates).
This might have been right in the 1980s, but modern compilers are much better.
Functions don't always push and pop the stack, especially if they're leaf functions or have tail calls. Also, functions are often inlined, and can be inlined even if they are defined in other translation units (this is called link-time optimization).
But you're right that in general, when optimizations are turned off, a macro be inlined and a function won't be inlined. Either version may take more space, it depends on the particulars of the macro/function.
A function uses space in two ways: the body uses space, and the function call uses space. If the function body is very small, it may actually save space to inline it.
Yes your understanding is right. But you should also note that, no type checking in macro and it can lead to side effect. You should also be very careful in parenthesizing macros.
Your understanding is half correct. The point is that macros are resolved before compilation. You should think of them as sophisticated text replacement tools (that's oversimplifying it, but is mostly what it comes down to).
So the difference is when in the build process your code is used.
This is orthogonal to the question of what the compiler really does with it when it creates the final binary code. It is more or less free to do whatever it thinks is correct to produce the intended behaviour. In C++, you can only hint at your preference with the inline keyword. The compiler is free to ignore that hint.
Again, this is orthogonal to the whole preprocessor business. Nothing stops you from writing macros which result in C++ code using the inline keyword, after all. Likewise, nobody stops you from writing macros which result in a lot of recursive C++ functions which the compiler will probably not be able to inline even if wanted to do.
The conclusion is that your question is wrong. It's a general question of having binaries with a lot of inlined functions vs. binaries with a lot of real function calls. Macros are just one technique you can use to influence the tradeoff in one way or the other, and you will ask yourself the same general question without macros.
The assumption that inlining a function will always trade space for speed is wrong. Inlining the wrong (i.e. too big) functions will even have a negative impact on speed. As is always the case with such opimisations, do not guess but measure.
You should read the FAQ on this: "Do inline functions improve performance?"

Resources