Skip to content

Commit 5765cfe

Browse files
committed
Transform proconfig for faster execution.
Store function config settings in lists to avoid the need to parse and allocate for each function execution. Speedup is modest but significant. Additionally, this change also seems cleaner and supports some other performance improvements under discussion. Discussion: https://postgr.es/m/04c8592dbd694e4114a3ed87139a7a04e4363030.camel@j-davis.com Reviewed-by: Nathan Bossart
1 parent bee263b commit 5765cfe

File tree

3 files changed

+60
-16
lines changed

3 files changed

+60
-16
lines changed

src/backend/utils/fmgr/fmgr.c

+20-9
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,8 @@ struct fmgr_security_definer_cache
612612
{
613613
FmgrInfo flinfo; /* lookup info for target function */
614614
Oid userid; /* userid to set, or InvalidOid */
615-
ArrayType *proconfig; /* GUC values to set, or NULL */
615+
List *configNames; /* GUC names to set, or NIL */
616+
List *configValues; /* GUC values to set, or NIL */
616617
Datum arg; /* passthrough argument for plugin modules */
617618
};
618619

@@ -634,6 +635,8 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
634635
FmgrInfo *save_flinfo;
635636
Oid save_userid;
636637
int save_sec_context;
638+
ListCell *lc1;
639+
ListCell *lc2;
637640
volatile int save_nestlevel;
638641
PgStat_FunctionCallUsage fcusage;
639642

@@ -666,8 +669,11 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
666669
&isnull);
667670
if (!isnull)
668671
{
672+
ArrayType *array;
669673
oldcxt = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
670-
fcache->proconfig = DatumGetArrayTypePCopy(datum);
674+
array = DatumGetArrayTypeP(datum);
675+
TransformGUCArray(array, &fcache->configNames,
676+
&fcache->configValues);
671677
MemoryContextSwitchTo(oldcxt);
672678
}
673679

@@ -680,7 +686,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
680686

681687
/* GetUserIdAndSecContext is cheap enough that no harm in a wasted call */
682688
GetUserIdAndSecContext(&save_userid, &save_sec_context);
683-
if (fcache->proconfig) /* Need a new GUC nesting level */
689+
if (fcache->configNames != NIL) /* Need a new GUC nesting level */
684690
save_nestlevel = NewGUCNestLevel();
685691
else
686692
save_nestlevel = 0; /* keep compiler quiet */
@@ -689,12 +695,17 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
689695
SetUserIdAndSecContext(fcache->userid,
690696
save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
691697

692-
if (fcache->proconfig)
698+
forboth(lc1, fcache->configNames, lc2, fcache->configValues)
693699
{
694-
ProcessGUCArray(fcache->proconfig,
695-
(superuser() ? PGC_SUSET : PGC_USERSET),
696-
PGC_S_SESSION,
697-
GUC_ACTION_SAVE);
700+
GucContext context = superuser() ? PGC_SUSET : PGC_USERSET;
701+
GucSource source = PGC_S_SESSION;
702+
GucAction action = GUC_ACTION_SAVE;
703+
char *name = lfirst(lc1);
704+
char *value = lfirst(lc2);
705+
706+
(void) set_config_option(name, value,
707+
context, source,
708+
action, true, 0, false);
698709
}
699710

700711
/* function manager hook */
@@ -737,7 +748,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
737748

738749
fcinfo->flinfo = save_flinfo;
739750

740-
if (fcache->proconfig)
751+
if (fcache->configNames != NIL)
741752
AtEOXact_GUC(true, save_nestlevel);
742753
if (OidIsValid(fcache->userid))
743754
SetUserIdAndSecContext(save_userid, save_sec_context);

src/backend/utils/misc/guc.c

+38-7
Original file line numberDiff line numberDiff line change
@@ -6215,14 +6215,12 @@ ParseLongOption(const char *string, char **name, char **value)
62156215

62166216

62176217
/*
6218-
* Handle options fetched from pg_db_role_setting.setconfig,
6219-
* pg_proc.proconfig, etc. Caller must specify proper context/source/action.
6220-
*
6221-
* The array parameter must be an array of TEXT (it must not be NULL).
6218+
* Transform array of GUC settings into lists of names and values. The lists
6219+
* are faster to process in cases where the settings must be applied
6220+
* repeatedly (e.g. for each function invocation).
62226221
*/
62236222
void
6224-
ProcessGUCArray(ArrayType *array,
6225-
GucContext context, GucSource source, GucAction action)
6223+
TransformGUCArray(ArrayType *array, List **names, List **values)
62266224
{
62276225
int i;
62286226

@@ -6231,6 +6229,8 @@ ProcessGUCArray(ArrayType *array,
62316229
Assert(ARR_NDIM(array) == 1);
62326230
Assert(ARR_LBOUND(array)[0] == 1);
62336231

6232+
*names = NIL;
6233+
*values = NIL;
62346234
for (i = 1; i <= ARR_DIMS(array)[0]; i++)
62356235
{
62366236
Datum d;
@@ -6262,14 +6262,45 @@ ProcessGUCArray(ArrayType *array,
62626262
continue;
62636263
}
62646264

6265+
*names = lappend(*names, name);
6266+
*values = lappend(*values, value);
6267+
6268+
pfree(s);
6269+
}
6270+
}
6271+
6272+
6273+
/*
6274+
* Handle options fetched from pg_db_role_setting.setconfig,
6275+
* pg_proc.proconfig, etc. Caller must specify proper context/source/action.
6276+
*
6277+
* The array parameter must be an array of TEXT (it must not be NULL).
6278+
*/
6279+
void
6280+
ProcessGUCArray(ArrayType *array,
6281+
GucContext context, GucSource source, GucAction action)
6282+
{
6283+
List *gucNames;
6284+
List *gucValues;
6285+
ListCell *lc1;
6286+
ListCell *lc2;
6287+
6288+
TransformGUCArray(array, &gucNames, &gucValues);
6289+
forboth(lc1, gucNames, lc2, gucValues)
6290+
{
6291+
char *name = lfirst(lc1);
6292+
char *value = lfirst(lc2);
6293+
62656294
(void) set_config_option(name, value,
62666295
context, source,
62676296
action, true, 0, false);
62686297

62696298
pfree(name);
62706299
pfree(value);
6271-
pfree(s);
62726300
}
6301+
6302+
list_free(gucNames);
6303+
list_free(gucValues);
62736304
}
62746305

62756306

src/include/utils/guc.h

+2
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,8 @@ extern void AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt);
391391
extern char *GetConfigOptionByName(const char *name, const char **varname,
392392
bool missing_ok);
393393

394+
extern void TransformGUCArray(ArrayType *array, List **configNames,
395+
List **configValues);
394396
extern void ProcessGUCArray(ArrayType *array,
395397
GucContext context, GucSource source, GucAction action);
396398
extern ArrayType *GUCArrayAdd(ArrayType *array, const char *name, const char *value);

0 commit comments

Comments
 (0)