From 799bf9c14b1c7e023e0436a2f6509cc1acca5df5 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Tue, 3 Oct 2017 00:36:42 -0700 Subject: [PATCH 4/6] Use one stringbuffer for all rows printed in printtup.c. This avoids newly allocating, and then possibly growing, the stringbuffer for every row. For wide rows this can substantially reduce memory allocator overhead, at the price of not reducing memory usage after outputting an especially wide row. --- src/backend/access/common/printtup.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c index 20d20e623e..07bebd7033 100644 --- a/src/backend/access/common/printtup.c +++ b/src/backend/access/common/printtup.c @@ -57,6 +57,7 @@ typedef struct typedef struct { DestReceiver pub; /* publicly-known function pointers */ + StringInfoData buf; /* output buffer */ Portal portal; /* the Portal we are printing from */ bool sendDescrip; /* send RowDescription at startup? */ TupleDesc attrinfo; /* The attr info we are set up for */ @@ -251,6 +252,8 @@ printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs) int16 *formats = myState->portal->formats; int i; + initStringInfo(&myState->buf); + /* get rid of any old data */ if (myState->myinfo) pfree(myState->myinfo); @@ -302,7 +305,7 @@ printtup(TupleTableSlot *slot, DestReceiver *self) TupleDesc typeinfo = slot->tts_tupleDescriptor; DR_printtup *myState = (DR_printtup *) self; MemoryContext oldcontext; - StringInfoData buf; + StringInfo buf = &myState->buf; int natts = typeinfo->natts; int i; @@ -319,9 +322,9 @@ printtup(TupleTableSlot *slot, DestReceiver *self) /* * Prepare a DataRow message (note buffer is in per-row context) */ - pq_beginmessage(&buf, 'D'); + pq_beginmessage_pre(buf, 'D'); - pq_sendint(&buf, natts, 2); + pq_sendint(buf, natts, 2); /* * send the attributes of this tuple @@ -333,7 +336,7 @@ printtup(TupleTableSlot *slot, DestReceiver *self) if (slot->tts_isnull[i]) { - pq_sendint(&buf, -1, 4); + pq_sendint(buf, -1, 4); continue; } @@ -354,7 +357,7 @@ printtup(TupleTableSlot *slot, DestReceiver *self) char *outputstr; outputstr = OutputFunctionCall(&thisState->finfo, attr); - pq_sendcountedtext(&buf, outputstr, strlen(outputstr), false); + pq_sendcountedtext(buf, outputstr, strlen(outputstr), false); } else { @@ -362,13 +365,13 @@ printtup(TupleTableSlot *slot, DestReceiver *self) bytea *outputbytes; outputbytes = SendFunctionCall(&thisState->finfo, attr); - pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4); - pq_sendbytes(&buf, VARDATA(outputbytes), + pq_sendint(buf, VARSIZE(outputbytes) - VARHDRSZ, 4); + pq_sendbytes(buf, VARDATA(outputbytes), VARSIZE(outputbytes) - VARHDRSZ); } } - pq_endmessage(&buf); + pq_endmessage_keep(buf); /* Return to caller's context, and flush row's temporary memory */ MemoryContextSwitchTo(oldcontext); -- 2.14.1.536.g6867272d5b.dirty