Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 913ec71

Browse files
committed
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
1 parent 697e1d0 commit 913ec71

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/backend/utils/error/elog.c

+13
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,19 @@ err_gettext(const char *str)
219219
#endif
220220
}
221221

222+
/*
223+
* errstart_cold
224+
* A simple wrapper around errstart, but hinted to be "cold". Supporting
225+
* compilers are more likely to move code for branches containing this
226+
* function into an area away from the calling function's code. This can
227+
* result in more commonly executed code being more compact and fitting
228+
* on fewer cache lines.
229+
*/
230+
pg_attribute_cold bool
231+
errstart_cold(int elevel, const char *domain)
232+
{
233+
return errstart(elevel, domain);
234+
}
222235

223236
/*
224237
* errstart --- begin an error-reporting cycle

src/include/utils/elog.h

+13-1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,15 @@
111111
* ereport_domain() directly, or preferably they can override the TEXTDOMAIN
112112
* macro.
113113
*
114+
* When __builtin_constant_p is available and elevel >= ERROR we make a call
115+
* to errstart_cold() instead of errstart(). This version of the function is
116+
* marked with pg_attribute_cold which will coax supporting compilers into
117+
* generating code which is more optimized towards non-ERROR cases. Because
118+
* we use __builtin_constant_p() in the condition, when elevel is not a
119+
* compile-time constant, or if it is, but it's < ERROR, the compiler has no
120+
* need to generate any code for this branch. It can simply call errstart()
121+
* unconditionally.
122+
*
114123
* If elevel >= ERROR, the call will not return; we try to inform the compiler
115124
* of that via pg_unreachable(). However, no useful optimization effect is
116125
* obtained unless the compiler sees elevel as a compile-time constant, else
@@ -124,7 +133,9 @@
124133
#define ereport_domain(elevel, domain, ...) \
125134
do { \
126135
pg_prevent_errno_in_scope(); \
127-
if (errstart(elevel, domain)) \
136+
if (__builtin_constant_p(elevel) && (elevel) >= ERROR ? \
137+
errstart_cold(elevel, domain) : \
138+
errstart(elevel, domain)) \
128139
__VA_ARGS__, errfinish(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \
129140
if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \
130141
pg_unreachable(); \
@@ -146,6 +157,7 @@
146157

147158
#define TEXTDOMAIN NULL
148159

160+
extern bool pg_attribute_cold errstart_cold(int elevel, const char *domain);
149161
extern bool errstart(int elevel, const char *domain);
150162
extern void errfinish(const char *filename, int lineno, const char *funcname);
151163

0 commit comments

Comments
 (0)