Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4c119fb

Browse files
committed
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 FreundDiscussion:https://postgr.es/m/20170914063418.sckdzgjfrsbekae4@alap3.anarazel.de
1 parentcff440d commit4c119fb

File tree

3 files changed

+138
-47
lines changed

3 files changed

+138
-47
lines changed

‎src/backend/access/common/printtup.c

Lines changed: 108 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ static bool printtup_internal_20(TupleTableSlot *slot, DestReceiver *self);
3232
staticvoidprinttup_shutdown(DestReceiver*self);
3333
staticvoidprinttup_destroy(DestReceiver*self);
3434

35+
staticvoidSendRowDescriptionCols_2(StringInfobuf,TupleDesctypeinfo,
36+
List*targetlist,int16*formats);
37+
staticvoidSendRowDescriptionCols_3(StringInfobuf,TupleDesctypeinfo,
38+
List*targetlist,int16*formats);
3539

3640
/* ----------------------------------------------------------------
3741
*printtup / debugtup support
@@ -161,7 +165,8 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
161165
* descriptor of the tuples.
162166
*/
163167
if (myState->sendDescrip)
164-
SendRowDescriptionMessage(typeinfo,
168+
SendRowDescriptionMessage(&myState->buf,
169+
typeinfo,
165170
FetchPortalTargetList(portal),
166171
portal->formats);
167172

@@ -189,61 +194,126 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
189194
* send zeroes for the format codes in that case.
190195
*/
191196
void
192-
SendRowDescriptionMessage(TupleDesctypeinfo,List*targetlist,int16*formats)
197+
SendRowDescriptionMessage(StringInfobuf,TupleDesctypeinfo,
198+
List*targetlist,int16*formats)
193199
{
194200
intnatts=typeinfo->natts;
195201
intproto=PG_PROTOCOL_MAJOR(FrontendProtocol);
202+
203+
/* tuple descriptor message type */
204+
pq_beginmessage_reuse(buf,'T');
205+
/* # of attrs in tuples */
206+
pq_sendint16(buf,natts);
207+
208+
if (proto >=3)
209+
SendRowDescriptionCols_3(buf,typeinfo,targetlist,formats);
210+
else
211+
SendRowDescriptionCols_2(buf,typeinfo,targetlist,formats);
212+
213+
pq_endmessage_reuse(buf);
214+
}
215+
216+
/*
217+
* Send description for each column when using v3+ protocol
218+
*/
219+
staticvoid
220+
SendRowDescriptionCols_3(StringInfobuf,TupleDesctypeinfo,List*targetlist,int16*formats)
221+
{
222+
intnatts=typeinfo->natts;
196223
inti;
197-
StringInfoDatabuf;
198224
ListCell*tlist_item=list_head(targetlist);
199225

200-
pq_beginmessage(&buf,'T');/* tuple descriptor message type */
201-
pq_sendint(&buf,natts,2);/* # of attrs in tuples */
226+
/*
227+
* Preallocate memory for the entire message to be sent. That allows to
228+
* use the significantly faster inline pqformat.h functions and to avoid
229+
* reallocations.
230+
*
231+
* Have to overestimate the size of the column-names, to account for
232+
* character set overhead.
233+
*/
234+
enlargeStringInfo(buf, (NAMEDATALEN*MAX_CONVERSION_GROWTH/* attname */
235+
+sizeof(Oid)/* resorigtbl */
236+
+sizeof(AttrNumber)/* resorigcol */
237+
+sizeof(Oid)/* atttypid */
238+
+sizeof(int16)/* attlen */
239+
+sizeof(int32)/* attypmod */
240+
+sizeof(int16)/* format */
241+
)*natts);
202242

203243
for (i=0;i<natts;++i)
204244
{
205245
Form_pg_attributeatt=TupleDescAttr(typeinfo,i);
206246
Oidatttypid=att->atttypid;
207247
int32atttypmod=att->atttypmod;
248+
Oidresorigtbl;
249+
AttrNumberresorigcol;
250+
int16format;
251+
252+
/*
253+
* If column is a domain, send the base type and typmod instead.
254+
* Lookup before sending any ints, for efficiency.
255+
*/
256+
atttypid=getBaseTypeAndTypmod(atttypid,&atttypmod);
208257

209-
pq_sendstring(&buf,NameStr(att->attname));
210-
/* column ID info appears in protocol 3.0 and up */
211-
if (proto >=3)
258+
/* Do we have a non-resjunk tlist item? */
259+
while (tlist_item&&
260+
((TargetEntry*)lfirst(tlist_item))->resjunk)
261+
tlist_item=lnext(tlist_item);
262+
if (tlist_item)
212263
{
213-
/* Do we have a non-resjunk tlist item? */
214-
while (tlist_item&&
215-
((TargetEntry*)lfirst(tlist_item))->resjunk)
216-
tlist_item=lnext(tlist_item);
217-
if (tlist_item)
218-
{
219-
TargetEntry*tle= (TargetEntry*)lfirst(tlist_item);
220-
221-
pq_sendint(&buf,tle->resorigtbl,4);
222-
pq_sendint(&buf,tle->resorigcol,2);
223-
tlist_item=lnext(tlist_item);
224-
}
225-
else
226-
{
227-
/* No info available, so send zeroes */
228-
pq_sendint(&buf,0,4);
229-
pq_sendint(&buf,0,2);
230-
}
264+
TargetEntry*tle= (TargetEntry*)lfirst(tlist_item);
265+
266+
resorigtbl=tle->resorigtbl;
267+
resorigcol=tle->resorigcol;
268+
tlist_item=lnext(tlist_item);
231269
}
232-
/* If column is a domain, send the base type and typmod instead */
233-
atttypid=getBaseTypeAndTypmod(atttypid,&atttypmod);
234-
pq_sendint(&buf, (int)atttypid,sizeof(atttypid));
235-
pq_sendint(&buf,att->attlen,sizeof(att->attlen));
236-
pq_sendint(&buf,atttypmod,sizeof(atttypmod));
237-
/* format info appears in protocol 3.0 and up */
238-
if (proto >=3)
270+
else
239271
{
240-
if (formats)
241-
pq_sendint(&buf,formats[i],2);
242-
else
243-
pq_sendint(&buf,0,2);
272+
/* No info available, so send zeroes */
273+
resorigtbl=0;
274+
resorigcol=0;
244275
}
276+
277+
if (formats)
278+
format=formats[i];
279+
else
280+
format=0;
281+
282+
pq_writestring(buf,NameStr(att->attname));
283+
pq_writeint32(buf,resorigtbl);
284+
pq_writeint16(buf,resorigcol);
285+
pq_writeint32(buf,atttypid);
286+
pq_writeint16(buf,att->attlen);
287+
pq_writeint32(buf,atttypmod);
288+
pq_writeint16(buf,format);
289+
}
290+
}
291+
292+
/*
293+
* Send description for each column when using v2 protocol
294+
*/
295+
staticvoid
296+
SendRowDescriptionCols_2(StringInfobuf,TupleDesctypeinfo,List*targetlist,int16*formats)
297+
{
298+
intnatts=typeinfo->natts;
299+
inti;
300+
301+
for (i=0;i<natts;++i)
302+
{
303+
Form_pg_attributeatt=TupleDescAttr(typeinfo,i);
304+
Oidatttypid=att->atttypid;
305+
int32atttypmod=att->atttypmod;
306+
307+
/* If column is a domain, send the base type and typmod instead */
308+
atttypid=getBaseTypeAndTypmod(atttypid,&atttypmod);
309+
310+
pq_sendstring(buf,NameStr(att->attname));
311+
/* column ID only info appears in protocol 3.0 and up */
312+
pq_sendint32(buf,atttypid);
313+
pq_sendint16(buf,att->attlen);
314+
pq_sendint32(buf,atttypmod);
315+
/* format info only appears in protocol 3.0 and up */
245316
}
246-
pq_endmessage(&buf);
247317
}
248318

249319
/*

‎src/backend/tcop/postgres.c

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ static bool RecoveryConflictPending = false;
165165
staticboolRecoveryConflictRetryable= true;
166166
staticProcSignalReasonRecoveryConflictReason;
167167

168+
/* reused buffer to pass to SendRowDescriptionMessage() */
169+
staticMemoryContextrow_description_context=NULL;
170+
staticStringInfoDatarow_description_buf;
171+
168172
/* ----------------------------------------------------------------
169173
*decls for routines only used in this file
170174
* ----------------------------------------------------------------
@@ -2315,7 +2319,6 @@ static void
23152319
exec_describe_statement_message(constchar*stmt_name)
23162320
{
23172321
CachedPlanSource*psrc;
2318-
StringInfoDatabuf;
23192322
inti;
23202323

23212324
/*
@@ -2371,16 +2374,17 @@ exec_describe_statement_message(const char *stmt_name)
23712374
/*
23722375
* First describe the parameters...
23732376
*/
2374-
pq_beginmessage(&buf,'t');/* parameter description message type */
2375-
pq_sendint(&buf,psrc->num_params,2);
2377+
pq_beginmessage_reuse(&row_description_buf,'t');/* parameter description
2378+
* message type */
2379+
pq_sendint(&row_description_buf,psrc->num_params,2);
23762380

23772381
for (i=0;i<psrc->num_params;i++)
23782382
{
23792383
Oidptype=psrc->param_types[i];
23802384

2381-
pq_sendint(&buf, (int)ptype,4);
2385+
pq_sendint(&row_description_buf, (int)ptype,4);
23822386
}
2383-
pq_endmessage(&buf);
2387+
pq_endmessage_reuse(&row_description_buf);
23842388

23852389
/*
23862390
* Next send RowDescription or NoData to describe the result...
@@ -2392,7 +2396,10 @@ exec_describe_statement_message(const char *stmt_name)
23922396
/* Get the plan's primary targetlist */
23932397
tlist=CachedPlanGetTargetList(psrc,NULL);
23942398

2395-
SendRowDescriptionMessage(psrc->resultDesc,tlist,NULL);
2399+
SendRowDescriptionMessage(&row_description_buf,
2400+
psrc->resultDesc,
2401+
tlist,
2402+
NULL);
23962403
}
23972404
else
23982405
pq_putemptymessage('n');/* NoData */
@@ -2444,7 +2451,8 @@ exec_describe_portal_message(const char *portal_name)
24442451
return;/* can't actually do anything... */
24452452

24462453
if (portal->tupDesc)
2447-
SendRowDescriptionMessage(portal->tupDesc,
2454+
SendRowDescriptionMessage(&row_description_buf,
2455+
portal->tupDesc,
24482456
FetchPortalTargetList(portal),
24492457
portal->formats);
24502458
else
@@ -3830,6 +3838,19 @@ PostgresMain(int argc, char *argv[],
38303838
"MessageContext",
38313839
ALLOCSET_DEFAULT_SIZES);
38323840

3841+
/*
3842+
* Create memory context and buffer used for RowDescription messages. As
3843+
* SendRowDescriptionMessage(), via exec_describe_statement_message(), is
3844+
* frequently executed for ever single statement, we don't want to
3845+
* allocate a separate buffer every time.
3846+
*/
3847+
row_description_context=AllocSetContextCreate(TopMemoryContext,
3848+
"RowDescriptionContext",
3849+
ALLOCSET_DEFAULT_SIZES);
3850+
MemoryContextSwitchTo(row_description_context);
3851+
initStringInfo(&row_description_buf);
3852+
MemoryContextSwitchTo(TopMemoryContext);
3853+
38333854
/*
38343855
* Remember stand-alone backend startup time
38353856
*/

‎src/include/access/printtup.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ extern DestReceiver *printtup_create_DR(CommandDest dest);
2020

2121
externvoidSetRemoteDestReceiverParams(DestReceiver*self,Portalportal);
2222

23-
externvoidSendRowDescriptionMessage(TupleDesctypeinfo,List*targetlist,
24-
int16*formats);
23+
externvoidSendRowDescriptionMessage(StringInfobuf,
24+
TupleDesctypeinfo,List*targetlist,int16*formats);
2525

2626
externvoiddebugStartup(DestReceiver*self,intoperation,
2727
TupleDesctypeinfo);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp