From 797a0e8d858b490df7a9e1526f76e49fe1e10215 Mon Sep 17 00:00:00 2001 From: Euler Taveira Date: Fri, 9 Mar 2018 17:37:36 +0000 Subject: [PATCH 2/8] Store number of tuples in WalRcvExecResult It seems to be a useful information while allocating memory for queries that returns more than one row. It reduces memory allocation for initial table synchronization. While in it, since we have the number of columns, allocate only nfields for cstrs instead of MaxTupleAttributeNumber. --- src/backend/replication/libpqwalreceiver/libpqwalreceiver.c | 9 ++++++--- src/backend/replication/logical/tablesync.c | 5 ++--- src/include/replication/walreceiver.h | 1 + 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c index 1e1695e..2533e3a 100644 --- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c +++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c @@ -865,6 +865,7 @@ libpqrcv_processTuples(PGresult *pgres, WalRcvExecResult *walres, errdetail("Expected %d fields, got %d fields.", nRetTypes, nfields))); + walres->ntuples = PQntuples(pgres); walres->tuplestore = tuplestore_begin_heap(true, false, work_mem); /* Create tuple descriptor corresponding to expected result. */ @@ -875,7 +876,7 @@ libpqrcv_processTuples(PGresult *pgres, WalRcvExecResult *walres, attinmeta = TupleDescGetAttInMetadata(walres->tupledesc); /* No point in doing more here if there were no tuples returned. */ - if (PQntuples(pgres) == 0) + if (walres->ntuples == 0) return; /* Create temporary context for local allocations. */ @@ -884,15 +885,17 @@ libpqrcv_processTuples(PGresult *pgres, WalRcvExecResult *walres, ALLOCSET_DEFAULT_SIZES); /* Process returned rows. */ - for (tupn = 0; tupn < PQntuples(pgres); tupn++) + for (tupn = 0; tupn < walres->ntuples; tupn++) { - char *cstrs[MaxTupleAttributeNumber]; + char **cstrs; CHECK_FOR_INTERRUPTS(); /* Do the allocations in temporary context. */ oldcontext = MemoryContextSwitchTo(rowcontext); + cstrs = palloc(nfields * sizeof(char *)); + /* * Fill cstrs with null-terminated strings of column values. */ diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c index f285813..e119781 100644 --- a/src/backend/replication/logical/tablesync.c +++ b/src/backend/replication/logical/tablesync.c @@ -720,9 +720,8 @@ fetch_remote_table_info(char *nspname, char *relname, (errmsg("could not fetch table info for table \"%s.%s\": %s", nspname, relname, res->err))); - /* We don't know the number of rows coming, so allocate enough space. */ - lrel->attnames = palloc0(MaxTupleAttributeNumber * sizeof(char *)); - lrel->atttyps = palloc0(MaxTupleAttributeNumber * sizeof(Oid)); + lrel->attnames = palloc0(res->ntuples * sizeof(char *)); + lrel->atttyps = palloc0(res->ntuples * sizeof(Oid)); lrel->attkeys = NULL; natt = 0; diff --git a/src/include/replication/walreceiver.h b/src/include/replication/walreceiver.h index 5913b58..62f63f9 100644 --- a/src/include/replication/walreceiver.h +++ b/src/include/replication/walreceiver.h @@ -197,6 +197,7 @@ typedef struct WalRcvExecResult char *err; Tuplestorestate *tuplestore; TupleDesc tupledesc; + int ntuples; } WalRcvExecResult; /* libpqwalreceiver hooks */ -- 2.7.4