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

Commit40301c1

Browse files
committed
Speed up plpgsql function startup by doing fewer pallocs.
Previously, copy_plpgsql_datum did a separate palloc for each variableneeding instance-local storage. In simple benchmarks this made for anoticeable fraction of the total runtime. Improve it by precalculatingthe space needed for all of a function's variables and doing just onepalloc for all of them.In passing, remove PLPGSQL_DTYPE_EXPR from the list of plpgsql "datum"types, since in fact it has nothing in common with the others, and thereis noplace that needs to discriminate on the basis of dtype between anexpression and any type of datum. And add comments clarifying whichdatum struct fields are generic and which aren't.Tom Lane, reviewed by Pavel StehuleDiscussion:https://postgr.es/m/11986.1514407114@sss.pgh.pa.us
1 parent4b93f57 commit40301c1

File tree

4 files changed

+130
-86
lines changed

4 files changed

+130
-86
lines changed

‎src/pl/plpgsql/src/pl_comp.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2183,12 +2183,29 @@ plpgsql_adddatum(PLpgSQL_datum *new)
21832183
staticvoid
21842184
plpgsql_finish_datums(PLpgSQL_function*function)
21852185
{
2186+
Sizecopiable_size=0;
21862187
inti;
21872188

21882189
function->ndatums=plpgsql_nDatums;
21892190
function->datums=palloc(sizeof(PLpgSQL_datum*)*plpgsql_nDatums);
21902191
for (i=0;i<plpgsql_nDatums;i++)
2192+
{
21912193
function->datums[i]=plpgsql_Datums[i];
2194+
2195+
/* This must agree with copy_plpgsql_datums on what is copiable */
2196+
switch (function->datums[i]->dtype)
2197+
{
2198+
casePLPGSQL_DTYPE_VAR:
2199+
copiable_size+=MAXALIGN(sizeof(PLpgSQL_var));
2200+
break;
2201+
casePLPGSQL_DTYPE_REC:
2202+
copiable_size+=MAXALIGN(sizeof(PLpgSQL_rec));
2203+
break;
2204+
default:
2205+
break;
2206+
}
2207+
}
2208+
function->copiable_size=copiable_size;
21922209
}
21932210

21942211

‎src/pl/plpgsql/src/pl_exec.c

Lines changed: 62 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ static HTAB *shared_cast_hash = NULL;
235235
staticvoidcoerce_function_result_tuple(PLpgSQL_execstate*estate,
236236
TupleDesctupdesc);
237237
staticvoidplpgsql_exec_error_callback(void*arg);
238-
staticPLpgSQL_datum*copy_plpgsql_datum(PLpgSQL_datum*datum);
238+
staticvoidcopy_plpgsql_datums(PLpgSQL_execstate*estate,
239+
PLpgSQL_function*func);
239240
staticMemoryContextget_stmt_mcontext(PLpgSQL_execstate*estate);
240241
staticvoidpush_stmt_mcontext(PLpgSQL_execstate*estate);
241242
staticvoidpop_stmt_mcontext(PLpgSQL_execstate*estate);
@@ -458,8 +459,7 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
458459
* Make local execution copies of all the datums
459460
*/
460461
estate.err_text=gettext_noop("during initialization of execution state");
461-
for (i=0;i<estate.ndatums;i++)
462-
estate.datums[i]=copy_plpgsql_datum(func->datums[i]);
462+
copy_plpgsql_datums(&estate,func);
463463

464464
/*
465465
* Store the actual call argument values into the appropriate variables
@@ -859,8 +859,7 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
859859
* Make local execution copies of all the datums
860860
*/
861861
estate.err_text=gettext_noop("during initialization of execution state");
862-
for (i=0;i<estate.ndatums;i++)
863-
estate.datums[i]=copy_plpgsql_datum(func->datums[i]);
862+
copy_plpgsql_datums(&estate,func);
864863

865864
/*
866865
* Put the OLD and NEW tuples into record variables
@@ -1153,7 +1152,6 @@ plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata)
11531152
{
11541153
PLpgSQL_execstateestate;
11551154
ErrorContextCallbackplerrcontext;
1156-
inti;
11571155
intrc;
11581156
PLpgSQL_var*var;
11591157

@@ -1174,8 +1172,7 @@ plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata)
11741172
* Make local execution copies of all the datums
11751173
*/
11761174
estate.err_text=gettext_noop("during initialization of execution state");
1177-
for (i=0;i<estate.ndatums;i++)
1178-
estate.datums[i]=copy_plpgsql_datum(func->datums[i]);
1175+
copy_plpgsql_datums(&estate,func);
11791176

11801177
/*
11811178
* Assign the special tg_ variables
@@ -1290,57 +1287,73 @@ plpgsql_exec_error_callback(void *arg)
12901287
* Support function for initializing local execution variables
12911288
* ----------
12921289
*/
1293-
staticPLpgSQL_datum*
1294-
copy_plpgsql_datum(PLpgSQL_datum*datum)
1290+
staticvoid
1291+
copy_plpgsql_datums(PLpgSQL_execstate*estate,
1292+
PLpgSQL_function*func)
12951293
{
1296-
PLpgSQL_datum*result;
1294+
intndatums=estate->ndatums;
1295+
PLpgSQL_datum**indatums;
1296+
PLpgSQL_datum**outdatums;
1297+
char*workspace;
1298+
char*ws_next;
1299+
inti;
12971300

1298-
switch (datum->dtype)
1299-
{
1300-
casePLPGSQL_DTYPE_VAR:
1301-
{
1302-
PLpgSQL_var*new=palloc(sizeof(PLpgSQL_var));
1301+
/* Allocate local datum-pointer array */
1302+
estate->datums= (PLpgSQL_datum**)
1303+
palloc(sizeof(PLpgSQL_datum*)*ndatums);
13031304

1304-
memcpy(new,datum,sizeof(PLpgSQL_var));
1305-
/* should be preset to null/non-freeable */
1306-
Assert(new->isnull);
1307-
Assert(!new->freeval);
1305+
/*
1306+
* To reduce palloc overhead, we make a single palloc request for all the
1307+
* space needed for locally-instantiated datums.
1308+
*/
1309+
workspace=palloc(func->copiable_size);
1310+
ws_next=workspace;
13081311

1309-
result= (PLpgSQL_datum*)new;
1310-
}
1311-
break;
1312+
/* Fill datum-pointer array, copying datums into workspace as needed */
1313+
indatums=func->datums;
1314+
outdatums=estate->datums;
1315+
for (i=0;i<ndatums;i++)
1316+
{
1317+
PLpgSQL_datum*indatum=indatums[i];
1318+
PLpgSQL_datum*outdatum;
13121319

1313-
casePLPGSQL_DTYPE_REC:
1314-
{
1315-
PLpgSQL_rec*new=palloc(sizeof(PLpgSQL_rec));
1320+
/* This must agree with plpgsql_finish_datums on what is copiable */
1321+
switch (indatum->dtype)
1322+
{
1323+
casePLPGSQL_DTYPE_VAR:
1324+
outdatum= (PLpgSQL_datum*)ws_next;
1325+
memcpy(outdatum,indatum,sizeof(PLpgSQL_var));
1326+
ws_next+=MAXALIGN(sizeof(PLpgSQL_var));
1327+
break;
13161328

1317-
memcpy(new,datum,sizeof(PLpgSQL_rec));
1318-
/* should be preset to empty */
1319-
Assert(new->erh==NULL);
1329+
casePLPGSQL_DTYPE_REC:
1330+
outdatum= (PLpgSQL_datum*)ws_next;
1331+
memcpy(outdatum,indatum,sizeof(PLpgSQL_rec));
1332+
ws_next+=MAXALIGN(sizeof(PLpgSQL_rec));
1333+
break;
13201334

1321-
result= (PLpgSQL_datum*)new;
1322-
}
1323-
break;
1335+
casePLPGSQL_DTYPE_ROW:
1336+
casePLPGSQL_DTYPE_RECFIELD:
1337+
casePLPGSQL_DTYPE_ARRAYELEM:
13241338

1325-
casePLPGSQL_DTYPE_ROW:
1326-
casePLPGSQL_DTYPE_RECFIELD:
1327-
casePLPGSQL_DTYPE_ARRAYELEM:
1339+
/*
1340+
* These datum records are read-only at runtime, so no need to
1341+
* copy them (well, RECFIELD and ARRAYELEM contain cached
1342+
* data, but we'd just as soon centralize the caching anyway).
1343+
*/
1344+
outdatum=indatum;
1345+
break;
13281346

1329-
/*
1330-
* These datum records are read-only at runtime, so no need to
1331-
* copy them (well, RECFIELD and ARRAYELEM contain cached data,
1332-
* but we'd just as soon centralize the caching anyway)
1333-
*/
1334-
result=datum;
1335-
break;
1347+
default:
1348+
elog(ERROR,"unrecognized dtype: %d",indatum->dtype);
1349+
outdatum=NULL;/* keep compiler quiet */
1350+
break;
1351+
}
13361352

1337-
default:
1338-
elog(ERROR,"unrecognized dtype: %d",datum->dtype);
1339-
result=NULL;/* keep compiler quiet */
1340-
break;
1353+
outdatums[i]=outdatum;
13411354
}
13421355

1343-
returnresult;
1356+
Assert(ws_next==workspace+func->copiable_size);
13441357
}
13451358

13461359
/*
@@ -3504,8 +3517,8 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
35043517

35053518
estate->found_varno=func->found_varno;
35063519
estate->ndatums=func->ndatums;
3507-
estate->datums=palloc(sizeof(PLpgSQL_datum*)*estate->ndatums);
3508-
/*caller is expected to fill the datums array */
3520+
estate->datums=NULL;
3521+
/*the datums array will be filled by copy_plpgsql_datums() */
35093522
estate->datum_context=CurrentMemoryContext;
35103523

35113524
/* initialize our ParamListInfo with appropriate hook functions */

‎src/pl/plpgsql/src/pl_gram.y

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,6 @@ decl_statement: decl_varname decl_const decl_datatype decl_collate decl_notnull
564564

565565
curname_def = palloc0(sizeof(PLpgSQL_expr));
566566

567-
curname_def->dtype = PLPGSQL_DTYPE_EXPR;
568567
strcpy(buf,"SELECT");
569568
cp1 =new->refname;
570569
cp2 = buf + strlen(buf);
@@ -2697,7 +2696,6 @@ read_sql_construct(int until,
26972696
}
26982697

26992698
expr = palloc0(sizeof(PLpgSQL_expr));
2700-
expr->dtype= PLPGSQL_DTYPE_EXPR;
27012699
expr->query= pstrdup(ds.data);
27022700
expr->plan= NULL;
27032701
expr->paramnos= NULL;
@@ -2944,7 +2942,6 @@ make_execsql_stmt(int firsttoken, int location)
29442942
ds.data[--ds.len] = '\0';
29452943

29462944
expr = palloc0(sizeof(PLpgSQL_expr));
2947-
expr->dtype= PLPGSQL_DTYPE_EXPR;
29482945
expr->query= pstrdup(ds.data);
29492946
expr->plan= NULL;
29502947
expr->paramnos= NULL;
@@ -3816,7 +3813,6 @@ read_cursor_args(PLpgSQL_var *cursor, int until, const char *expected)
38163813
appendStringInfoChar(&ds, ';');
38173814

38183815
expr = palloc0(sizeof(PLpgSQL_expr));
3819-
expr->dtype= PLPGSQL_DTYPE_EXPR;
38203816
expr->query= pstrdup(ds.data);
38213817
expr->plan= NULL;
38223818
expr->paramnos= NULL;

‎src/pl/plpgsql/src/plpgsql.h

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ typedef enum PLpgSQL_datum_type
6363
PLPGSQL_DTYPE_ROW,
6464
PLPGSQL_DTYPE_REC,
6565
PLPGSQL_DTYPE_RECFIELD,
66-
PLPGSQL_DTYPE_ARRAYELEM,
67-
PLPGSQL_DTYPE_EXPR
66+
PLPGSQL_DTYPE_ARRAYELEM
6867
}PLpgSQL_datum_type;
6968

7069
/*
@@ -188,39 +187,11 @@ typedef struct PLpgSQL_type
188187
int32atttypmod;/* typmod (taken from someplace else) */
189188
}PLpgSQL_type;
190189

191-
/*
192-
* Generic datum array item
193-
*
194-
* PLpgSQL_datum is the common supertype for PLpgSQL_expr, PLpgSQL_var,
195-
* PLpgSQL_row, PLpgSQL_rec, PLpgSQL_recfield, and PLpgSQL_arrayelem
196-
*/
197-
typedefstructPLpgSQL_datum
198-
{
199-
PLpgSQL_datum_typedtype;
200-
intdno;
201-
}PLpgSQL_datum;
202-
203-
/*
204-
* Scalar or composite variable
205-
*
206-
* The variants PLpgSQL_var, PLpgSQL_row, and PLpgSQL_rec share these
207-
* fields
208-
*/
209-
typedefstructPLpgSQL_variable
210-
{
211-
PLpgSQL_datum_typedtype;
212-
intdno;
213-
char*refname;
214-
intlineno;
215-
}PLpgSQL_variable;
216-
217190
/*
218191
* SQL Query to plan and execute
219192
*/
220193
typedefstructPLpgSQL_expr
221194
{
222-
PLpgSQL_datum_typedtype;
223-
intdno;
224195
char*query;
225196
SPIPlanPtrplan;
226197
Bitmapset*paramnos;/* all dnos referenced by this query */
@@ -249,6 +220,32 @@ typedef struct PLpgSQL_expr
249220
LocalTransactionIdexpr_simple_lxid;
250221
}PLpgSQL_expr;
251222

223+
/*
224+
* Generic datum array item
225+
*
226+
* PLpgSQL_datum is the common supertype for PLpgSQL_var, PLpgSQL_row,
227+
* PLpgSQL_rec, PLpgSQL_recfield, and PLpgSQL_arrayelem.
228+
*/
229+
typedefstructPLpgSQL_datum
230+
{
231+
PLpgSQL_datum_typedtype;
232+
intdno;
233+
}PLpgSQL_datum;
234+
235+
/*
236+
* Scalar or composite variable
237+
*
238+
* The variants PLpgSQL_var, PLpgSQL_row, and PLpgSQL_rec share these
239+
* fields.
240+
*/
241+
typedefstructPLpgSQL_variable
242+
{
243+
PLpgSQL_datum_typedtype;
244+
intdno;
245+
char*refname;
246+
intlineno;
247+
}PLpgSQL_variable;
248+
252249
/*
253250
* Scalar variable
254251
*/
@@ -258,11 +255,18 @@ typedef struct PLpgSQL_var
258255
intdno;
259256
char*refname;
260257
intlineno;
258+
/* end of PLpgSQL_variable fields */
261259

260+
boolisconst;
261+
boolnotnull;
262262
PLpgSQL_type*datatype;
263-
intisconst;
264-
intnotnull;
265263
PLpgSQL_expr*default_val;
264+
265+
/*
266+
* Variables declared as CURSOR FOR <query> are mostly like ordinary
267+
* scalar variables of type refcursor, but they have these additional
268+
* properties:
269+
*/
266270
PLpgSQL_expr*cursor_explicit_expr;
267271
intcursor_explicit_argrow;
268272
intcursor_options;
@@ -286,6 +290,7 @@ typedef struct PLpgSQL_row
286290
intdno;
287291
char*refname;
288292
intlineno;
293+
/* end of PLpgSQL_variable fields */
289294

290295
/*
291296
* rowtupdesc is only set up if we might need to convert the row into a
@@ -308,6 +313,8 @@ typedef struct PLpgSQL_rec
308313
intdno;
309314
char*refname;
310315
intlineno;
316+
/* end of PLpgSQL_variable fields */
317+
311318
Oidrectypeid;/* declared type of variable */
312319
/* RECFIELDs for this record are chained together for easy access */
313320
intfirstfield;/* dno of first RECFIELD, or -1 if none */
@@ -322,6 +329,8 @@ typedef struct PLpgSQL_recfield
322329
{
323330
PLpgSQL_datum_typedtype;
324331
intdno;
332+
/* end of PLpgSQL_datum fields */
333+
325334
char*fieldname;/* name of field */
326335
intrecparentno;/* dno of parent record */
327336
intnextfield;/* dno of next child, or -1 if none */
@@ -337,6 +346,8 @@ typedef struct PLpgSQL_arrayelem
337346
{
338347
PLpgSQL_datum_typedtype;
339348
intdno;
349+
/* end of PLpgSQL_datum fields */
350+
340351
PLpgSQL_expr*subscript;
341352
intarrayparentno;/* dno of parent array variable */
342353

@@ -884,6 +895,7 @@ typedef struct PLpgSQL_function
884895
/* the datums representing the function's local variables */
885896
intndatums;
886897
PLpgSQL_datum**datums;
898+
Sizecopiable_size;/* space for locally instantiated datums */
887899

888900
/* function body parsetree */
889901
PLpgSQL_stmt_block*action;
@@ -920,8 +932,14 @@ typedef struct PLpgSQL_execstate
920932
ResourceOwnertuple_store_owner;
921933
ReturnSetInfo*rsi;
922934

923-
/* the datums representing the function's local variables */
924935
intfound_varno;
936+
937+
/*
938+
* The datums representing the function's local variables. Some of these
939+
* are local storage in this execstate, but some just point to the shared
940+
* copy belonging to the PLpgSQL_function, depending on whether or not we
941+
* need any per-execution state for the datum's dtype.
942+
*/
925943
intndatums;
926944
PLpgSQL_datum**datums;
927945
/* context containing variable values (same as func's SPI_proc context) */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp