LWN.net Logo

How likely should likely() be?

Newcomers to the kernel code base are often surprised by the appearance of (what seems to be) a bunch of calls to functions called likely() and unlikely(). These calls always appear in conditional tests, along these lines:

    if (likely(some_condition)) {
	/* Do something */
    }

In fact, likely() and unlikely() are not function calls at all; instead, they are hints to the compiler. If the compiler knows that one outcome is far more likely than the other, it can optimize the code it generates accordingly. On some architectures, this information can also be encoded into the object code, where it will override the branch prediction normally done by the processor.

David Woodhouse noted that the differing interpretation of these directives by different architectures makes it hard to know when likely() and unlikely() should be used. If the result of one of those directives is just a bit of code optimization, they should be used liberally whenever the programmer knows that one outcome will happen more often than the other. On some architectures, however, the cost of guessing wrong is fairly high, and these directives should only be used where the odds are overwhelmingly in favor of one outcome.

David's proposal is to replace likely() and unlikely() with a new probable() macro:

    probable(condition, percent)

Where "percent" is the programmer's estimation of how often the condition will evaluate true. Each architecture could then decide what to tell the compiler based on the given percentage.

Rusty Russell has a more straightforward answer, saying that these directives should be rarely used.

Sometimes, unlikely()/likely() help code readability. But generally it should be considered the register keyword of the 2000's: if the case isn't ABSOLUTELY CRYSTAL CLEAR, or doesn't show up on benchmarks, disdain is appropriate.

The "disdain" approach seems more likely to be adopted than a new macro. There will be very few code paths where these directives will make a measurable difference. And the fact is that programmers often guess wrong about which code paths will be taken how often.

David would also like to add a probability to the get_unaligned() macro, which is used to access data which might not have the alignment required by the processor. Some architectures can handle any alignment; on those, get_unaligned() expands to a direct pointer dereference. Others require that unaligned access be done via multiple, smaller fetches or stores. Of those, some architectures can fix up an unaligned access attempt in an exception handler, and others cannot. For architectures which can fix unaligned accesses, it might be faster to take an occasional exception if the probability of an unaligned access is small. Adding a probability to the get_unaligned() macro (and put_unaligned() as well) would allow each architecture to optimize those accesses. Whether the resulting performance improvement would justify the effort remains to be seen.


(Log in to post comments)

How likely should likely() be?

Posted Feb 12, 2004 13:33 UTC (Thu) by zooko (subscriber, #2589) [Link]

Can GCC's profile-directed optimization be used on the kernel?

If so, you would think that this would obviate the need for programmer-specified hints in the source code.

How likely should likely() be?

Posted Feb 14, 2004 20:48 UTC (Sat) by giraffedata (subscriber, #1954) [Link]

Except that programmer-specified hints are a lot easier. Also, the hint to the code reader can be valuable too.

Where the code reader is concerned, the likely() notation is awful. I read this as "if some_condition is likely, then ..." A more appropriate notation would be

  assert(likely(some_condition));
  if (some_condition) ...

Furthermore, just minimizing the average time spent doing the branch isn't the only reason to do branch prediction hints. Consider

  if (fast_response_required) ...

Even if fast_response_required is rarely true, I may want the code optimized for the case that it is. That gets me to

  optimize_for(fast_response_required)
or maybe
  if (fast_response_required) {
    optimize_for_this_case();
  }

Copyright © 2004, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds