I have a custom ASSERT(...)
macro which I use in a C++ application.
#include <stdlib.h>
#include <iostream>
/// ASSERT(expr) checks if expr is true. If not, error details are logged
/// and the process is exited with a non-zero code.
#ifdef INCLUDE_ASSERTIONS
#define ASSERT(expr) \
if (!(expr)) { \
char buf[4096]; \
snprintf (buf, 4096, "Assertion failed in \"%s\", line %d\n%s\n", \
__FILE__, __LINE__, #expr); \
std::cerr << buf; \
::abort(); \
} \
else // This 'else' exists to catch the user's following semicolon
#else
#define ASSERT(expr)
#endif
Recently I was reading some Linux kernel module code and came across the existence of likely(...)
and unlikely(...)
macros. These provide a hint to the CPU that a given branch is more likely, and that the pipeline should optimise for that path.
Assertions are, by definition, expected to evaluate to true (i.e. likely
).
Can I provide a similar hint in my ASSERT
macro? What's the underlying mechanism here?
Obviously I will measure for any difference in performance, but in theory should it make any difference?
I only run my code on Linux, but would be interested to know if there's a cross platform way of doing this too. I'm also using gcc, but would like to support clang as well.
<cassert>
? – EmmuelaASSERT
s inside performance-critical loops then it really isn't going to make any difference. Also branch prediction is pretty good for consistent branches such as this these days, so even in a performance-critical loop it shouldn't make much difference on a modern CPU. – HealRelease
andRelWithDebInfo
builds. It's controlled viaINCLUDE_ASSERTIONS
which is independent of the build type. – DichromicCan I provide a similar hint in my ASSERT macro?
Yes, you can of course uselikely
andunlikely
if you so wish. – Actiniaelse
. Empty statements are perfectly acceptable in C, and don't change the meaning of the code at all.if (foo) {};
is no different fromif (foo) {}
. – Hispidelse
, the macro could gobble up a followingelse
:if (x) ASSERT(y) else z();
-- with the current version, this gives an error (good!) but if you omit the else in the macro definition, theelse z()
will attach inside the expansion of theASSERT
macro (bad!). Of course, this is why we usedo { ... } while(0)
in macros. – Bathsheebelse // This 'else' exists to catch the user's following semicolon
" - the usual way to do that is to wrap the body of the macro in ado { /* ... macro body here ... */ } while (false)
block. – Downdraft