postgres.git / summary / log / commit / refs

commit    913ec71d682e99852cc188a7edbdccd02d42b4b3
Author:   David Rowley <drowley@postgresql.org>
Date:     Mon Nov 23 23:04:42 2020 +0000
First released in: 14.0

    Improve compiler code layout in elog/ereport ERROR calls
    
    Here we use a bit of preprocessor trickery to coax supporting compilers
    into laying out their generated code so that the code that's in the same
    branch as elog(ERROR)/ereport(ERROR) calls is moved away from the hot
    path.  Effectively, this reduces the size of the hot code meaning that it
    can sit on fewer cache lines.
    
    Performance improvements of between 10-15% have been seen on highly CPU
    bound workloads using pgbench's TPC-b benchmark.
    
    What's achieved here is very similar to putting the error condition inside
    an unlikely() macro. For example;
    
    if (unlikely(x < 0))
        elog(ERROR, "invalid x value");
    
    now there's no need to make use of unlikely() here as the common macro
    used by elog and ereport will now see that elevel is >= ERROR and make use
    of a pg_attribute_cold marked version of errstart().
    
    When elevel < ERROR or if it cannot be determined to be constant, the
    original behavior is maintained.
    
    Author: David Rowley
    Reviewed-by: Andres Freund, Peter Eisentraut
    Discussion: https://postgr.es/m/CAApHDvrVpasrEzLL2er7p9iwZFZ%3DJj6WisePcFeunwfrV0js_A%40mail.gmail.com


src/backend/utils/error/elog.c | 13 +++++++++++++ src/include/utils/elog.h | 14 +++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 1ba47c194b2..42c5e052b64 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -219,6 +219,19 @@ err_gettext(const char *str) #endif } +/* + * errstart_cold + * A simple wrapper around errstart, but hinted to be "cold". Supporting + * compilers are more likely to move code for branches containing this + * function into an area away from the calling function's code. This can + * result in more commonly executed code being more compact and fitting + * on fewer cache lines. + */ +pg_attribute_cold bool +errstart_cold(int elevel, const char *domain) +{ + return errstart(elevel, domain); +} /* * errstart --- begin an error-reporting cycle diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 1e09ee05418..270bfbcfe5d 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -111,6 +111,15 @@ * ereport_domain() directly, or preferably they can override the TEXTDOMAIN * macro. * + * When __builtin_constant_p is available and elevel >= ERROR we make a call + * to errstart_cold() instead of errstart(). This version of the function is + * marked with pg_attribute_cold which will coax supporting compilers into + * generating code which is more optimized towards non-ERROR cases. Because + * we use __builtin_constant_p() in the condition, when elevel is not a + * compile-time constant, or if it is, but it's < ERROR, the compiler has no + * need to generate any code for this branch. It can simply call errstart() + * unconditionally. + * * If elevel >= ERROR, the call will not return; we try to inform the compiler * of that via pg_unreachable(). However, no useful optimization effect is * obtained unless the compiler sees elevel as a compile-time constant, else @@ -124,7 +133,9 @@ #define ereport_domain(elevel, domain, ...) \ do { \ pg_prevent_errno_in_scope(); \ - if (errstart(elevel, domain)) \ + if (__builtin_constant_p(elevel) && (elevel) >= ERROR ? \ + errstart_cold(elevel, domain) : \ + errstart(elevel, domain)) \ __VA_ARGS__, errfinish(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \ if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \ pg_unreachable(); \ @@ -146,6 +157,7 @@ #define TEXTDOMAIN NULL +extern bool pg_attribute_cold errstart_cold(int elevel, const char *domain); extern bool errstart(int elevel, const char *domain); extern void errfinish(const char *filename, int lineno, const char *funcname); [parent: 697e1d02f53f]