Use one stringbuffer for all rows printed in printtup.c.
authorAndres Freund <[email protected]>
Tue, 3 Oct 2017 07:36:42 +0000 (00:36 -0700)
committerAndres Freund <[email protected]>
Sun, 8 Oct 2017 16:41:55 +0000 (09:41 -0700)
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

index 20d20e623e80d805395ecd9f32a2bacaf51f1294..07bebd703377995ccd1fea12e97f93ee83444b51 100644 (file)
@@ -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);