Could abuse in Macros degrade performance?

I have a very long code called millions of times, I noticed that if I change all the macros to built-in functions, the code will work much faster.

Can you explain why this is so? Are macros just a replacement for text? Unlike inline functions, which can be a function call?

+6
source share
4 answers

A macro is a text entity and, as such, usually creates more executable code. Each time you call a macro, code is entered (well, not necessarily, the macro may be empty ... but in principle).
Inline functions, on the other hand, can work just like macros, but they also cannot be inline.

In the general case, the inline rather a weak hint than a requirement, in any case, compilers will now be reasonably built into functions (or will refrain from this) based on heuristics, mainly the number of pseudo-instructions.

Built-in functions can thus cause the compiler not to include the function at all or to embed it several times, and then call it non-inined in addition.
Surprisingly, non-inlining can actually be faster than inlining, since it reduces the overall code size and therefore the number of misses in the cache and TLB.

+9
source

This will depend on the particular macro call and function you are using. A particular macro can actually compile a longer set of operations than an inline function. It is often best not to use a macro for certain processes. A built-in function allows the compiler to print validation and optimize various processes. Macros will be subject to several errors and may actually cause various inefficiencies (for example, moving variables to and from storage).

In any case, since you really see this in your code, you can say that the compiler can optimize your inline code, rather than blindly embed it in a text extension.

Please note that the google search in inline macros show some discussion of this issue.

+7
source

In addition to forcing inlining, macros can also be detrimental to speed if they are not carefully written so as not to evaluate their arguments twice. Take, for example, this low-functional macro and its built-in function:

 #define square(x) ((x)*(x)) inline long square(long x) { return x*x; } 

Now when you call them with the square(foo) variable, they are equivalent. The vesion macro expands to ((foo)*(foo)) , which is one multiplication, just like a function if it is built-in.

However, if you call them using square(expensiveComputation(foo)) , the result of the macro is that expensiveComputation() is called twice. In contrast, an inline function behaves like any function: its argument is evaluated once before the function body is executed.

Of course, you can write a macro using the gnu extension of compound statements (see http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html for documentation on this) to avoid double-valuation:

 #define square(x) ({ \ long square_temp_variable = (x); \ square_temp_variable*square_temp_variable; \ }) 

But this is a lot of trouble, and it makes the code unsportsmanlike. So, it is better to stick with the built-in functions.

+6
source

In general, it is recommended that function style macros be replaced with built-in functions wherever possible.

not only do you experience some unpleasant a = MIN(i++, 50) traps a = MIN(i++, 50) , for example, you also get security types, and, as mentioned in some comments, you avoid repeatedly evaluating arguments that can have a very bad performance impact.

+3
source

All Articles