diff options
author | Andres Freund <andres@anarazel.de> | 2017-10-11 16:49:31 -0700 |
---|---|---|
committer | Andres Freund <andres@anarazel.de> | 2017-10-11 17:23:23 -0700 |
commit | 4c119fbcd49ba882791c7b99a1e934b985468e9f (patch) | |
tree | 3ab2f089ccdeac4a38e94552b6edf9557b3c7793 /src/backend/tcop/postgres.c | |
parent | cff440d368690f94fbda1a475277e90ea2263843 (diff) | |
download | postgresql-4c119fbcd49ba882791c7b99a1e934b985468e9f.tar.gz postgresql-4c119fbcd49ba882791c7b99a1e934b985468e9f.zip |
Improve performance of SendRowDescriptionMessage.
There's three categories of changes leading to better performance:
- Splitting the per-attribute part of SendRowDescriptionMessage into a
v2 and a v3 version allows avoiding branches for every attribute.
- Preallocating the size of the buffer to be big enough for all
attributes and then using pq_write* avoids unnecessary buffer
size checks & resizing.
- Reusing a persistently allocated StringInfo for all
SendRowDescriptionMessage() invocations avoids repeated allocations
& reallocations.
Author: Andres Freund
Discussion: https://postgr.es/m/20170914063418.sckdzgjfrsbekae4@alap3.anarazel.de
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r-- | src/backend/tcop/postgres.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index edea6f177bb..338ce81331d 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -165,6 +165,10 @@ static bool RecoveryConflictPending = false; static bool RecoveryConflictRetryable = true; static ProcSignalReason RecoveryConflictReason; +/* reused buffer to pass to SendRowDescriptionMessage() */ +static MemoryContext row_description_context = NULL; +static StringInfoData row_description_buf; + /* ---------------------------------------------------------------- * decls for routines only used in this file * ---------------------------------------------------------------- @@ -2315,7 +2319,6 @@ static void exec_describe_statement_message(const char *stmt_name) { CachedPlanSource *psrc; - StringInfoData buf; int i; /* @@ -2371,16 +2374,17 @@ exec_describe_statement_message(const char *stmt_name) /* * First describe the parameters... */ - pq_beginmessage(&buf, 't'); /* parameter description message type */ - pq_sendint(&buf, psrc->num_params, 2); + pq_beginmessage_reuse(&row_description_buf, 't'); /* parameter description + * message type */ + pq_sendint(&row_description_buf, psrc->num_params, 2); for (i = 0; i < psrc->num_params; i++) { Oid ptype = psrc->param_types[i]; - pq_sendint(&buf, (int) ptype, 4); + pq_sendint(&row_description_buf, (int) ptype, 4); } - pq_endmessage(&buf); + pq_endmessage_reuse(&row_description_buf); /* * Next send RowDescription or NoData to describe the result... @@ -2392,7 +2396,10 @@ exec_describe_statement_message(const char *stmt_name) /* Get the plan's primary targetlist */ tlist = CachedPlanGetTargetList(psrc, NULL); - SendRowDescriptionMessage(psrc->resultDesc, tlist, NULL); + SendRowDescriptionMessage(&row_description_buf, + psrc->resultDesc, + tlist, + NULL); } else pq_putemptymessage('n'); /* NoData */ @@ -2444,7 +2451,8 @@ exec_describe_portal_message(const char *portal_name) return; /* can't actually do anything... */ if (portal->tupDesc) - SendRowDescriptionMessage(portal->tupDesc, + SendRowDescriptionMessage(&row_description_buf, + portal->tupDesc, FetchPortalTargetList(portal), portal->formats); else @@ -3831,6 +3839,19 @@ PostgresMain(int argc, char *argv[], ALLOCSET_DEFAULT_SIZES); /* + * Create memory context and buffer used for RowDescription messages. As + * SendRowDescriptionMessage(), via exec_describe_statement_message(), is + * frequently executed for ever single statement, we don't want to + * allocate a separate buffer every time. + */ + row_description_context = AllocSetContextCreate(TopMemoryContext, + "RowDescriptionContext", + ALLOCSET_DEFAULT_SIZES); + MemoryContextSwitchTo(row_description_context); + initStringInfo(&row_description_buf); + MemoryContextSwitchTo(TopMemoryContext); + + /* * Remember stand-alone backend startup time */ if (!IsUnderPostmaster) |