Asterisk INLINE Optimization

Asterisk developers who have made use of one of our function attributes called “force_inline” should be aware we are discouraging it.  Why? Let’s get to some background first. Asterisk core developers try to do a great job at optimizing the codebase.  After spending a few months interacting with the Asterisk core developers here at Hunstville, I’ve come to appreciate the dedication they put into making sure memory is efficiently used.  Nothing can waste memory, everything has to be methodically distributed. The result is an application that runs pretty efficiently. It is no small feat to run code that handles hundreds of calls at a time, and every effort pays off.

Asterisk uses the highest compiler CPU optimization level (O3) by default.  Should developers by any chance chose to make Asterisk run slower (they may want to do some debugging), they can enable a compiler flag called DONT_OPTIMIZE, easily configurable at the Menuselect settings.  On the other hand, should the developer prefer to enjoy faster performance, he should just leave the DONT_OPTIMIZE flag alone in its default off state.

GCC compilers are always trying to improve their optimization performance, and newer compiler versions are no exception. Therefore it is a good idea to leave the compiler alone when it comes to choosing what sections of code to optimize, otherwise we may find our code not really making the best use of the compiler.  The inline keyword is a good example.  By preceding some of the most commonly used functions with the inline keyword, the function may run faster after the code is optimized.  Inline causes the compiler to move the code of the called function into the calling function. This makes things slightly faster because there’s no need to push and pop stuff on and off the call stack.

The point of making a function inline is to hint to the compiler that it is worth making some form of extra effort to call the function faster than it would otherwise, generally by substituting the code of the function into its caller. As well as eliminating the need for a call and return sequence, it might allow the compiler to perform certain optimizations between the bodies of both functions.

Here is a simple example what the compiler does to your code after inlining it:

Before inline:

void SayHello() {
	printf("Hello world\n");
}
void myfunc() {
	SayHello();
}

After inline:

void myfunc() {
	printf("Hello world\n");
}

On the positive side certainly there are gains involved in not having to refer to the function definition at run time. On the negative side the compiled code can become pretty large.

To declare a function inline, use the inline keyword in its declaration, like this:

static inline int max(int a, int b);

So far so good, we know the compiler will make the decision whether to apply our keyword or not. We basically add the inline keyword and let the compiler decide.  However, we also have the choice to shoot ourselves in the foot by going one step further and telling the compiler to inline no matter what.  This is achieved by adding the always_inline attribute to the function declaration.  We do that like this:

static inline int max(int a, int b) __attribute__((always_inline));

Putting always_inline in too many places, we have come to realize, is bad.  GCC version 8.2.1 for instance, documents a bug where provided Fedora 28 is present, and in addition to certain levels of multi-threading, arithmetic calculations may fail.  Using the always_inline or the inline attributes have been pretty common in the past by C developers, but newer compilers use ever more sophisticated inlining analysis. In short, always_inline is temporarily discouraged.

 

Leave a Reply

Your email address will not be published. Required fields are marked *


The reCAPTCHA verification period has expired. Please reload the page.

About the Author

What can we help you find?