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

Commit6c82d8d

Browse files
committed
Further reduce overhead for passing plpgsql variables to the executor.
This builds on commit21dcda2 by keepinga plpgsql function's shared ParamListInfo's entries for simple variables(PLPGSQL_DTYPE_VARs) valid at all times. That adds a few cycles to eachassignment to such variables, but saves significantly more cycles each timethey are used; so except in the pathological case of many dead stores, thisshould always be a win. Initial testing says it's good for about a 10%speedup of simple calculations; more in large functions with many datums.We can't use this method for row/record references unfortunately, so whatwe do for those is reset those ParamListInfo slots after use; which wecan skip doing unless some of them were actually evaluated during theprevious evaluation call. So this should frequently be a win as well,while worst case is that it's similar cost to the previous approach.Also, closer study suggests that the previous method of instantiating anew ParamListInfo array per evaluation is actually probably optimal forcursor-opening executor calls. The reason is that whatever is visible inthe array is going to get copied into the cursor portal via copyParamList.So if we used the function's main ParamListInfo for those calls, we'd endup with all of its DTYPE_VAR vars getting copied, which might well includelarge pass-by-reference values that the cursor actually has no need for.To avoid a possible net degradation in cursor cases, go back to creatingand filling a private ParamListInfo in those cases (which therefore will beexactly the same speed as before21dcda2). We still get some benefitout of this though, because this approach means that we only have to defendagainst copyParamList's try-to-fetch-every-slot behavior in the case of anunshared ParamListInfo; so plpgsql_param_fetch() can skip testingexpr->paramnos in the common case.To ensure that the main ParamListInfo's image of a DTYPE_VAR datum isalways valid, all assignments to such variables are now funneled throughassign_simple_var(). But this makes for cleaner and shorter code anyway.
1 parent2524046 commit6c82d8d

File tree

3 files changed

+359
-207
lines changed

3 files changed

+359
-207
lines changed

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

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ PLpgSQL_stmt_block *plpgsql_parse_result;
4242
staticintdatums_alloc;
4343
intplpgsql_nDatums;
4444
PLpgSQL_datum**plpgsql_Datums;
45-
staticintdatums_last=0;
45+
staticintdatums_last;
4646

4747
char*plpgsql_error_funcname;
4848
boolplpgsql_DumpExecTree= false;
@@ -104,6 +104,8 @@ static Node *make_datum_param(PLpgSQL_expr *expr, int dno, int location);
104104
staticPLpgSQL_row*build_row_from_class(OidclassOid);
105105
staticPLpgSQL_row*build_row_from_vars(PLpgSQL_variable**vars,intnumvars);
106106
staticPLpgSQL_type*build_datatype(HeapTupletypeTup,int32typmod,Oidcollation);
107+
staticvoidplpgsql_start_datums(void);
108+
staticvoidplpgsql_finish_datums(PLpgSQL_function*function);
107109
staticvoidcompute_function_hashkey(FunctionCallInfofcinfo,
108110
Form_pg_procprocStruct,
109111
PLpgSQL_func_hashkey*hashkey,
@@ -371,13 +373,7 @@ do_compile(FunctionCallInfo fcinfo,
371373
plpgsql_ns_init();
372374
plpgsql_ns_push(NameStr(procStruct->proname));
373375
plpgsql_DumpExecTree= false;
374-
375-
datums_alloc=128;
376-
plpgsql_nDatums=0;
377-
/* This is short-lived, so needn't allocate in function's cxt */
378-
plpgsql_Datums=MemoryContextAlloc(compile_tmp_cxt,
379-
sizeof(PLpgSQL_datum*)*datums_alloc);
380-
datums_last=0;
376+
plpgsql_start_datums();
381377

382378
switch (function->fn_is_trigger)
383379
{
@@ -758,10 +754,8 @@ do_compile(FunctionCallInfo fcinfo,
758754
function->fn_nargs=procStruct->pronargs;
759755
for (i=0;i<function->fn_nargs;i++)
760756
function->fn_argvarnos[i]=in_arg_varnos[i];
761-
function->ndatums=plpgsql_nDatums;
762-
function->datums=palloc(sizeof(PLpgSQL_datum*)*plpgsql_nDatums);
763-
for (i=0;i<plpgsql_nDatums;i++)
764-
function->datums[i]=plpgsql_Datums[i];
757+
758+
plpgsql_finish_datums(function);
765759

766760
/* Debug dump for completed functions */
767761
if (plpgsql_DumpExecTree)
@@ -804,7 +798,6 @@ plpgsql_compile_inline(char *proc_source)
804798
PLpgSQL_variable*var;
805799
intparse_rc;
806800
MemoryContextfunc_cxt;
807-
inti;
808801

809802
/*
810803
* Setup the scanner input and error info. We assume that this function
@@ -860,11 +853,7 @@ plpgsql_compile_inline(char *proc_source)
860853
plpgsql_ns_init();
861854
plpgsql_ns_push(func_name);
862855
plpgsql_DumpExecTree= false;
863-
864-
datums_alloc=128;
865-
plpgsql_nDatums=0;
866-
plpgsql_Datums=palloc(sizeof(PLpgSQL_datum*)*datums_alloc);
867-
datums_last=0;
856+
plpgsql_start_datums();
868857

869858
/* Set up as though in a function returning VOID */
870859
function->fn_rettype=VOIDOID;
@@ -911,10 +900,8 @@ plpgsql_compile_inline(char *proc_source)
911900
* Complete the function's info
912901
*/
913902
function->fn_nargs=0;
914-
function->ndatums=plpgsql_nDatums;
915-
function->datums=palloc(sizeof(PLpgSQL_datum*)*plpgsql_nDatums);
916-
for (i=0;i<plpgsql_nDatums;i++)
917-
function->datums[i]=plpgsql_Datums[i];
903+
904+
plpgsql_finish_datums(function);
918905

919906
/*
920907
* Pop the error context stack
@@ -1965,6 +1952,7 @@ plpgsql_build_record(const char *refname, int lineno, bool add2namespace)
19651952
rec->tup=NULL;
19661953
rec->tupdesc=NULL;
19671954
rec->freetup= false;
1955+
rec->freetupdesc= false;
19681956
plpgsql_adddatum((PLpgSQL_datum*)rec);
19691957
if (add2namespace)
19701958
plpgsql_ns_additem(PLPGSQL_NSTYPE_REC,rec->dno,rec->refname);
@@ -2311,6 +2299,22 @@ plpgsql_parse_err_condition(char *condname)
23112299
returnprev;
23122300
}
23132301

2302+
/* ----------
2303+
* plpgsql_start_datumsInitialize datum list at compile startup.
2304+
* ----------
2305+
*/
2306+
staticvoid
2307+
plpgsql_start_datums(void)
2308+
{
2309+
datums_alloc=128;
2310+
plpgsql_nDatums=0;
2311+
/* This is short-lived, so needn't allocate in function's cxt */
2312+
plpgsql_Datums=MemoryContextAlloc(compile_tmp_cxt,
2313+
sizeof(PLpgSQL_datum*)*datums_alloc);
2314+
/* datums_last tracks what's been seen by plpgsql_add_initdatums() */
2315+
datums_last=0;
2316+
}
2317+
23142318
/* ----------
23152319
* plpgsql_adddatumAdd a variable, record or row
23162320
*to the compiler's datum list.
@@ -2329,6 +2333,39 @@ plpgsql_adddatum(PLpgSQL_datum *new)
23292333
plpgsql_Datums[plpgsql_nDatums++]=new;
23302334
}
23312335

2336+
/* ----------
2337+
* plpgsql_finish_datumsCopy completed datum info into function struct.
2338+
*
2339+
* This is also responsible for building resettable_datums, a bitmapset
2340+
* of the dnos of all ROW, REC, and RECFIELD datums in the function.
2341+
* ----------
2342+
*/
2343+
staticvoid
2344+
plpgsql_finish_datums(PLpgSQL_function*function)
2345+
{
2346+
Bitmapset*resettable_datums=NULL;
2347+
inti;
2348+
2349+
function->ndatums=plpgsql_nDatums;
2350+
function->datums=palloc(sizeof(PLpgSQL_datum*)*plpgsql_nDatums);
2351+
for (i=0;i<plpgsql_nDatums;i++)
2352+
{
2353+
function->datums[i]=plpgsql_Datums[i];
2354+
switch (function->datums[i]->dtype)
2355+
{
2356+
casePLPGSQL_DTYPE_ROW:
2357+
casePLPGSQL_DTYPE_REC:
2358+
casePLPGSQL_DTYPE_RECFIELD:
2359+
resettable_datums=bms_add_member(resettable_datums,i);
2360+
break;
2361+
2362+
default:
2363+
break;
2364+
}
2365+
}
2366+
function->resettable_datums=resettable_datums;
2367+
}
2368+
23322369

23332370
/* ----------
23342371
* plpgsql_add_initdatumsMake an array of the datum numbers of

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp