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

Commit 422221c

Browse files
committed
Another SELECT speedup: extract OIDs of column print functions
only once per SELECT, not once per tuple. 10% here, 10% there, pretty soon you're talking about real speedups ...
1 parent 36693c0 commit 422221c

File tree

9 files changed

+390
-208
lines changed

9 files changed

+390
-208
lines changed

src/backend/access/common/printtup.c

+109-11
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.39 1999/01/24 22:50:58 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.40 1999/01/27 00:36:22 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -27,6 +27,10 @@
2727
#include <mb/pg_wchar.h>
2828
#endif
2929

30+
static void printtup_setup(DestReceiver* self, TupleDesc typeinfo);
31+
static void printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self);
32+
static void printtup_cleanup(DestReceiver* self);
33+
3034
/* ----------------------------------------------------------------
3135
* printtup / debugtup support
3236
* ----------------------------------------------------------------
@@ -64,26 +68,105 @@ getTypeOutAndElem(Oid type, Oid* typOutput, Oid* typElem)
6468
return 0;
6569
}
6670

71+
/* ----------------
72+
* Private state for a printtup destination object
73+
* ----------------
74+
*/
75+
typedef struct { /* Per-attribute information */
76+
Oid typoutput; /* Oid for the attribute's type output fn */
77+
Oid typelem; /* typelem value to pass to the output fn */
78+
/* more soon... */
79+
} PrinttupAttrInfo;
80+
81+
typedef struct {
82+
DestReceiver pub; /* publicly-known function pointers */
83+
TupleDesc attrinfo; /* The attr info we are set up for */
84+
int nattrs;
85+
PrinttupAttrInfo *myinfo; /* Cached info about each attr */
86+
} DR_printtup;
87+
88+
/* ----------------
89+
* Initialize: create a DestReceiver for printtup
90+
* ----------------
91+
*/
92+
DestReceiver*
93+
printtup_create_DR()
94+
{
95+
DR_printtup* self = (DR_printtup*) palloc(sizeof(DR_printtup));
96+
97+
self->pub.receiveTuple = printtup;
98+
self->pub.setup = printtup_setup;
99+
self->pub.cleanup = printtup_cleanup;
100+
101+
self->attrinfo = NULL;
102+
self->nattrs = 0;
103+
self->myinfo = NULL;
104+
105+
return (DestReceiver*) self;
106+
}
107+
108+
static void
109+
printtup_setup(DestReceiver* self, TupleDesc typeinfo)
110+
{
111+
/* ----------------
112+
* We could set up the derived attr info at this time, but we postpone it
113+
* until the first call of printtup, for 3 reasons:
114+
* 1. We don't waste time (compared to the old way) if there are no
115+
* tuples at all to output.
116+
* 2. Checking in printtup allows us to handle the case that the tuples
117+
* change type midway through (although this probably can't happen in
118+
* the current executor).
119+
* 3. Right now, ExecutorRun passes a NULL for typeinfo anyway :-(
120+
* ----------------
121+
*/
122+
}
123+
124+
static void
125+
printtup_prepare_info(DR_printtup* myState, TupleDesc typeinfo, int numAttrs)
126+
{
127+
int i;
128+
129+
if (myState->myinfo)
130+
pfree(myState->myinfo); /* get rid of any old data */
131+
myState->myinfo = NULL;
132+
myState->attrinfo = typeinfo;
133+
myState->nattrs = numAttrs;
134+
if (numAttrs <= 0)
135+
return;
136+
myState->myinfo = (PrinttupAttrInfo*)
137+
palloc(numAttrs * sizeof(PrinttupAttrInfo));
138+
for (i = 0; i < numAttrs; i++)
139+
{
140+
PrinttupAttrInfo* thisState = myState->myinfo + i;
141+
getTypeOutAndElem((Oid) typeinfo->attrs[i]->atttypid,
142+
&thisState->typoutput, &thisState->typelem);
143+
}
144+
}
145+
67146
/* ----------------
68147
* printtup
69148
* ----------------
70149
*/
71-
void
72-
printtup(HeapTuple tuple, TupleDesc typeinfo)
150+
static void
151+
printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
73152
{
153+
DR_printtup *myState = (DR_printtup*) self;
74154
int i,
75155
j,
76156
k,
77157
outputlen;
78158
char *outputstr;
79159
Datum attr;
80160
bool isnull;
81-
Oid typoutput,
82-
typelem;
83161
#ifdef MULTIBYTE
84162
unsigned char *p;
85163
#endif
86164

165+
/* Set or update my derived attribute info, if needed */
166+
if (myState->attrinfo != typeinfo ||
167+
myState->nattrs != tuple->t_data->t_natts)
168+
printtup_prepare_info(myState, typeinfo, tuple->t_data->t_natts);
169+
87170
/* ----------------
88171
* tell the frontend to expect new tuple data (in ASCII style)
89172
* ----------------
@@ -120,10 +203,11 @@ printtup(HeapTuple tuple, TupleDesc typeinfo)
120203
attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
121204
if (isnull)
122205
continue;
123-
if (getTypeOutAndElem((Oid) typeinfo->attrs[i]->atttypid,
124-
&typoutput, &typelem))
206+
if (OidIsValid(myState->myinfo[i].typoutput))
125207
{
126-
outputstr = fmgr(typoutput, attr, typelem,
208+
outputstr = fmgr(myState->myinfo[i].typoutput,
209+
attr,
210+
myState->myinfo[i].typelem,
127211
typeinfo->attrs[i]->atttypmod);
128212
#ifdef MULTIBYTE
129213
p = pg_server_to_client(outputstr, strlen(outputstr));
@@ -147,6 +231,19 @@ printtup(HeapTuple tuple, TupleDesc typeinfo)
147231
}
148232
}
149233

234+
/* ----------------
235+
* printtup_cleanup
236+
* ----------------
237+
*/
238+
static void
239+
printtup_cleanup(DestReceiver* self)
240+
{
241+
DR_printtup* myState = (DR_printtup*) self;
242+
if (myState->myinfo)
243+
pfree(myState->myinfo);
244+
pfree(myState);
245+
}
246+
150247
/* ----------------
151248
* printatt
152249
* ----------------
@@ -190,7 +287,7 @@ showatts(char *name, TupleDesc tupleDesc)
190287
* ----------------
191288
*/
192289
void
193-
debugtup(HeapTuple tuple, TupleDesc typeinfo)
290+
debugtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
194291
{
195292
int i;
196293
Datum attr;
@@ -221,11 +318,12 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo)
221318
* We use a different data prefix, e.g. 'B' instead of 'D' to
222319
* indicate a tuple in internal (binary) form.
223320
*
224-
* This is same as printtup, except we don't use the typout func.
321+
* This is same as printtup, except we don't use the typout func,
322+
* and therefore have no need for persistent state.
225323
* ----------------
226324
*/
227325
void
228-
printtup_internal(HeapTuple tuple, TupleDesc typeinfo)
326+
printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
229327
{
230328
int i,
231329
j,

src/backend/executor/execMain.c

+26-14
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.63 1999/01/25 12:01:03 vadim Exp $
29+
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.64 1999/01/27 00:36:20 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -66,9 +66,10 @@ static void EndPlan(Plan *plan, EState *estate);
6666
static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan,
6767
Query *parseTree, CmdType operation,
6868
int numberTuples, ScanDirection direction,
69-
void (*printfunc) ());
70-
static void ExecRetrieve(TupleTableSlot *slot, void (*printfunc) (),
71-
EState *estate);
69+
DestReceiver *destfunc);
70+
static void ExecRetrieve(TupleTableSlot *slot,
71+
DestReceiver *destfunc,
72+
EState *estate);
7273
static void ExecAppend(TupleTableSlot *slot, ItemPointer tupleid,
7374
EState *estate);
7475
static void ExecDelete(TupleTableSlot *slot, ItemPointer tupleid,
@@ -171,7 +172,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
171172
Plan *plan;
172173
TupleTableSlot *result;
173174
CommandDest dest;
174-
void (*destination) ();
175+
DestReceiver *destfunc;
175176

176177
/******************
177178
* sanity checks
@@ -188,10 +189,19 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
188189
parseTree = queryDesc->parsetree;
189190
plan = queryDesc->plantree;
190191
dest = queryDesc->dest;
191-
destination = (void (*) ()) DestToFunction(dest);
192+
destfunc = DestToFunction(dest);
192193
estate->es_processed = 0;
193194
estate->es_lastoid = InvalidOid;
194195

196+
/******************
197+
* FIXME: the dest setup function ought to be handed the tuple desc
198+
* for the tuples to be output, but I'm not quite sure how to get that
199+
* info at this point. For now, passing NULL is OK because no existing
200+
* dest setup function actually uses the pointer.
201+
******************
202+
*/
203+
(*destfunc->setup) (destfunc, (TupleDesc) NULL);
204+
195205
switch (feature)
196206
{
197207

@@ -202,7 +212,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
202212
operation,
203213
ALL_TUPLES,
204214
ForwardScanDirection,
205-
destination);
215+
destfunc);
206216
break;
207217
case EXEC_FOR:
208218
result = ExecutePlan(estate,
@@ -211,7 +221,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
211221
operation,
212222
count,
213223
ForwardScanDirection,
214-
destination);
224+
destfunc);
215225
break;
216226

217227
/******************
@@ -225,7 +235,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
225235
operation,
226236
count,
227237
BackwardScanDirection,
228-
destination);
238+
destfunc);
229239
break;
230240

231241
/******************
@@ -240,14 +250,16 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
240250
operation,
241251
ONE_TUPLE,
242252
ForwardScanDirection,
243-
destination);
253+
destfunc);
244254
break;
245255
default:
246256
result = NULL;
247257
elog(DEBUG, "ExecutorRun: Unknown feature %d", feature);
248258
break;
249259
}
250260

261+
(*destfunc->cleanup) (destfunc);
262+
251263
return result;
252264
}
253265

@@ -745,7 +757,7 @@ ExecutePlan(EState *estate,
745757
CmdType operation,
746758
int numberTuples,
747759
ScanDirection direction,
748-
void (*printfunc) ())
760+
DestReceiver* destfunc)
749761
{
750762
JunkFilter *junkfilter;
751763

@@ -905,7 +917,7 @@ ExecutePlan(EState *estate,
905917
{
906918
case CMD_SELECT:
907919
ExecRetrieve(slot, /* slot containing tuple */
908-
printfunc, /* print function */
920+
destfunc, /* destination's tuple-receiver obj */
909921
estate); /* */
910922
result = slot;
911923
break;
@@ -961,7 +973,7 @@ ExecutePlan(EState *estate,
961973
*/
962974
static void
963975
ExecRetrieve(TupleTableSlot *slot,
964-
void (*printfunc) (),
976+
DestReceiver *destfunc,
965977
EState *estate)
966978
{
967979
HeapTuple tuple;
@@ -988,7 +1000,7 @@ ExecRetrieve(TupleTableSlot *slot,
9881000
* send the tuple to the front end (or the screen)
9891001
******************
9901002
*/
991-
(*printfunc) (tuple, attrtype);
1003+
(*destfunc->receiveTuple) (tuple, attrtype, destfunc);
9921004
IncrRetrieved();
9931005
(estate->es_processed)++;
9941006
}

src/backend/executor/spi.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* spi.c--
44
* Server Programming Interface
55
*
6-
* $Id: spi.c,v 1.30 1999/01/24 05:40:48 tgl Exp $
6+
* $Id: spi.c,v 1.31 1999/01/27 00:36:21 tgl Exp $
77
*
88
*-------------------------------------------------------------------------
99
*/
@@ -32,8 +32,6 @@ uint32 SPI_processed = 0;
3232
SPITupleTable *SPI_tuptable;
3333
int SPI_result;
3434

35-
void spi_printtup(HeapTuple tuple, TupleDesc tupdesc);
36-
3735
typedef struct
3836
{
3937
QueryTreeList *qtlist;
@@ -566,7 +564,7 @@ SPI_pfree(void *pointer)
566564
*
567565
*/
568566
void
569-
spi_printtup(HeapTuple tuple, TupleDesc tupdesc)
567+
spi_printtup(HeapTuple tuple, TupleDesc tupdesc, DestReceiver* self)
570568
{
571569
SPITupleTable *tuptable;
572570
MemoryContext oldcxt;

src/backend/libpq/be-dumpdata.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: be-dumpdata.c,v 1.20 1999/01/24 05:40:49 tgl Exp $
9+
* $Id: be-dumpdata.c,v 1.21 1999/01/27 00:36:12 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -208,7 +208,7 @@ be_typeinit(PortalEntry *entry,
208208
* ----------------
209209
*/
210210
void
211-
be_printtup(HeapTuple tuple, TupleDesc typeinfo)
211+
be_printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
212212
{
213213
int i;
214214
Datum attr;

src/backend/nodes/print.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.18 1998/09/01 04:29:10 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.19 1999/01/27 00:36:28 tgl Exp $
1111
*
1212
* HISTORY
1313
* AUTHOR DATE MAJOR EVENT
@@ -275,7 +275,7 @@ print_slot(TupleTableSlot *slot)
275275
return;
276276
}
277277

278-
debugtup(slot->val, slot->ttc_tupleDescriptor);
278+
debugtup(slot->val, slot->ttc_tupleDescriptor, NULL);
279279
}
280280

281281
static char *

0 commit comments

Comments
 (0)