简体   繁体   中英

In the C if-else statement, should the condition which is more likely to be true come first?

I happened to write a if-else statement, the condition would be false at most time(check a static pointer is assigned or not). Which one would be better for the compiler to optimize? Or they are just equal?. The function would be called so many times, so it is critical to optimize its performance.

void foo() {
  static int * p = NULL;
  if (p == NULL) {
     p = (int *) malloc( SIZE * sizeof(int)); 
  }
  //do something here
} 

void foo() {
  static int * p = NULL;
  if (p != NULL) {
    //do something here 
  } else {
    p = (int *) malloc( SIZE * sizeof(int));  
    //do something
  }
}

Some compilers can allow the dev to specify which is condition is more likely or unlikely to occur. This is heavily used in the Linux kernel.

In gcc, there's the likely(x) or unlikely(x) macros. Example:

if (unlikely(p == NULL)) {
    p = malloc(10);
}

If the function is called often enough to not be evicted from the branch predictor, then the predictor will take care of everything for you, since it will learn very quickly which is the "likely" branch.

Some compilers allow you to decorate conditionals with prediction hints. Check your vendor's documentation, and add a hint if you can.

Specific platforms document the default predictor behaviour (eg see the Intel Optimization Manual for x86), but it's best left to your compiler to implement that via the aforementioned hints. In fact, you don't really have a choice, since you don't control your compilers code generation anyway, so the only last measure left to you would be to write the code in machine code yourself and implement the platform's advice on default prediction.

At the end, it depends on the compiler and the optimization it does, which changes from compiler version, processor, compiler family...

My rule of thumb on this kind of subjects is to check on your actual platform by doing some extensive profiling. I usually also follow the rule "code first correctly, optimize later only if required". Trying to optimize upfront often leads to less readable code and design (and sometime, not even better performance).

Conditions are checked in order from left to right, this is in the C standard, thus allowing for conditionals like

if( ptr != NULL && ptr->member == value )

This also means that it makes sense to place the condition which is most likely to be false first.

http://msdn.microsoft.com/en-us/library/2bxt6kc4.aspx

If you looking for performance I wouldn't use malloc at all. Get Huge chunk of RAM and use it directly without allocation deallocation wrappers. Also consider using macros code will be bigger but performance also will increase.

#define ASSURE_PTR(a)      if (!a){ \
        a = (int *) malloc (SIZE * sizeof(int)); \
    }

If the function gets called often, any decent branch predictor would learn to predict the common path very quickly. Note that the code may be compiled differently than you expect since some compilers rely on static branch prediction , and may recognize this pattern.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM