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

Commit 867dd2d

Browse files
committed
Cache opaque handle for GUC option to avoid repeasted lookups.
When setting GUCs from proconfig, performance is important, and hash lookups in the GUC table are significant. Per suggestion from Robert Haas. Discussion: https://postgr.es/m/CA+TgmoYpKxhR3HOD9syK2XwcAUVPa0+ba0XPnwWBcYxtKLkyxA@mail.gmail.com Reviewed-by: John Naylor
1 parent c9c0589 commit 867dd2d

File tree

4 files changed

+84
-14
lines changed

4 files changed

+84
-14
lines changed

src/backend/utils/fmgr/fmgr.c

+24-7
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,7 @@ struct fmgr_security_definer_cache
613613
FmgrInfo flinfo; /* lookup info for target function */
614614
Oid userid; /* userid to set, or InvalidOid */
615615
List *configNames; /* GUC names to set, or NIL */
616+
List *configHandles; /* GUC handles to set, or NIL */
616617
List *configValues; /* GUC values to set, or NIL */
617618
Datum arg; /* passthrough argument for plugin modules */
618619
};
@@ -635,8 +636,9 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
635636
FmgrInfo *save_flinfo;
636637
Oid save_userid;
637638
int save_sec_context;
638-
ListCell *lc1;
639-
ListCell *lc2;
639+
ListCell *lc1,
640+
*lc2,
641+
*lc3;
640642
volatile int save_nestlevel;
641643
PgStat_FunctionCallUsage fcusage;
642644

@@ -670,11 +672,23 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
670672
if (!isnull)
671673
{
672674
ArrayType *array;
675+
ListCell *lc;
673676

674677
oldcxt = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
675678
array = DatumGetArrayTypeP(datum);
676679
TransformGUCArray(array, &fcache->configNames,
677680
&fcache->configValues);
681+
682+
/* transform names to config handles to avoid lookup cost */
683+
fcache->configHandles = NIL;
684+
foreach(lc, fcache->configNames)
685+
{
686+
char *name = (char *) lfirst(lc);
687+
688+
fcache->configHandles = lappend(fcache->configHandles,
689+
get_config_handle(name));
690+
}
691+
678692
MemoryContextSwitchTo(oldcxt);
679693
}
680694

@@ -696,17 +710,20 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
696710
SetUserIdAndSecContext(fcache->userid,
697711
save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
698712

699-
forboth(lc1, fcache->configNames, lc2, fcache->configValues)
713+
forthree(lc1, fcache->configNames,
714+
lc2, fcache->configHandles,
715+
lc3, fcache->configValues)
700716
{
701717
GucContext context = superuser() ? PGC_SUSET : PGC_USERSET;
702718
GucSource source = PGC_S_SESSION;
703719
GucAction action = GUC_ACTION_SAVE;
704720
char *name = lfirst(lc1);
705-
char *value = lfirst(lc2);
721+
config_handle *handle = lfirst(lc2);
722+
char *value = lfirst(lc3);
706723

707-
(void) set_config_option(name, value,
708-
context, source,
709-
action, true, 0, false);
724+
(void) set_config_with_handle(name, handle, value,
725+
context, source, GetUserId(),
726+
action, true, 0, false);
710727
}
711728

712729
/* function manager hook */

src/backend/utils/misc/guc.c

+50-7
Original file line numberDiff line numberDiff line change
@@ -3329,10 +3329,10 @@ set_config_option(const char *name, const char *value,
33293329
else
33303330
srole = BOOTSTRAP_SUPERUSERID;
33313331

3332-
return set_config_option_ext(name, value,
3333-
context, source, srole,
3334-
action, changeVal, elevel,
3335-
is_reload);
3332+
return set_config_with_handle(name, NULL, value,
3333+
context, source, srole,
3334+
action, changeVal, elevel,
3335+
is_reload);
33363336
}
33373337

33383338
/*
@@ -3355,6 +3355,27 @@ set_config_option_ext(const char *name, const char *value,
33553355
GucContext context, GucSource source, Oid srole,
33563356
GucAction action, bool changeVal, int elevel,
33573357
bool is_reload)
3358+
{
3359+
return set_config_with_handle(name, NULL, value,
3360+
context, source, srole,
3361+
action, changeVal, elevel,
3362+
is_reload);
3363+
}
3364+
3365+
3366+
/*
3367+
* set_config_with_handle: takes an optional 'handle' argument, which can be
3368+
* obtained by the caller from get_config_handle().
3369+
*
3370+
* This should be used by callers which repeatedly set the same config
3371+
* option(s), and want to avoid the overhead of a hash lookup each time.
3372+
*/
3373+
int
3374+
set_config_with_handle(const char *name, config_handle *handle,
3375+
const char *value,
3376+
GucContext context, GucSource source, Oid srole,
3377+
GucAction action, bool changeVal, int elevel,
3378+
bool is_reload)
33583379
{
33593380
struct config_generic *record;
33603381
union config_var_val newval_union;
@@ -3395,9 +3416,15 @@ set_config_option_ext(const char *name, const char *value,
33953416
(errcode(ERRCODE_INVALID_TRANSACTION_STATE),
33963417
errmsg("cannot set parameters during a parallel operation")));
33973418

3398-
record = find_option(name, true, false, elevel);
3399-
if (record == NULL)
3400-
return 0;
3419+
/* if handle is specified, no need to look up option */
3420+
if (!handle)
3421+
{
3422+
record = find_option(name, true, false, elevel);
3423+
if (record == NULL)
3424+
return 0;
3425+
}
3426+
else
3427+
record = handle;
34013428

34023429
/*
34033430
* Check if the option can be set at this time. See guc.h for the precise
@@ -4166,6 +4193,22 @@ set_config_option_ext(const char *name, const char *value,
41664193
}
41674194

41684195

4196+
/*
4197+
* Retrieve a config_handle for the given name, suitable for calling
4198+
* set_config_with_handle(). Only return handle to permanent GUC.
4199+
*/
4200+
config_handle *
4201+
get_config_handle(const char *name)
4202+
{
4203+
struct config_generic *gen = find_option(name, false, false, 0);
4204+
4205+
if (gen && ((gen->flags & GUC_CUSTOM_PLACEHOLDER) == 0))
4206+
return gen;
4207+
4208+
return NULL;
4209+
}
4210+
4211+
41694212
/*
41704213
* Set the fields for source file and line number the setting came from.
41714214
*/

src/include/utils/guc.h

+9
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ typedef struct ConfigVariable
144144
struct ConfigVariable *next;
145145
} ConfigVariable;
146146

147+
typedef struct config_generic config_handle;
148+
147149
extern bool ParseConfigFile(const char *config_file, bool strict,
148150
const char *calling_file, int calling_lineno,
149151
int depth, int elevel,
@@ -387,6 +389,13 @@ extern int set_config_option_ext(const char *name, const char *value,
387389
Oid srole,
388390
GucAction action, bool changeVal, int elevel,
389391
bool is_reload);
392+
extern int set_config_with_handle(const char *name, config_handle *handle,
393+
const char *value,
394+
GucContext context, GucSource source,
395+
Oid srole,
396+
GucAction action, bool changeVal,
397+
int elevel, bool is_reload);
398+
extern config_handle *get_config_handle(const char *name);
390399
extern void AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt);
391400
extern char *GetConfigOptionByName(const char *name, const char **varname,
392401
bool missing_ok);

src/tools/pgindent/typedefs.list

+1
Original file line numberDiff line numberDiff line change
@@ -3247,6 +3247,7 @@ collation_cache_entry
32473247
color
32483248
colormaprange
32493249
compare_context
3250+
config_handle
32503251
config_var_value
32513252
contain_aggs_of_level_context
32523253
contain_placeholder_references_context

0 commit comments

Comments
 (0)