mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-03-01 19:45:33 +08:00
Remove size increase in ExprEvalStep caused by hashed saops
50e17ad28
increased the size of ExprEvalStep from 64 bytes up to 88 bytes. Lots of effort was spent during the development of the current expression evaluation code to make an instance of this struct as small as possible. Making this struct larger than needed reduces CPU cache efficiency during expression evaluation which causes noticeable slowdowns during query execution. In order to reduce the size of the struct, here we remove the fn_addr field. The values from this field can be obtained via fcinfo, just with some extra pointer dereferencing. The extra indirection does not seem to cause any noticeable slowdowns. Various other fields have been moved into the ScalarArrayOpExprHashTable struct. These fields are only used when the ScalarArrayOpExprHashTable pointer has already been dereferenced, so no additional pointer dereferences occur for these. Here we also make hash_fcinfo_data the last field in ScalarArrayOpExprHashTable so that we can avoid a further pointer dereference to get the FunctionCallInfoBaseData. This also saves a call to palloc().50e17ad28
was added in 14, but it's too late to adjust the size of the ExprEvalStep in that version, so here we just backpatch to 15, which is currently in beta. Author: Andres Freund, David Rowley Discussion: https://postgr.es/m/20220616233130.rparivafipt6doj3@alap3.anarazel.de Backpatch-through: 15
This commit is contained in:
parent
16d52fc89d
commit
fe3caa1439
@ -1203,8 +1203,6 @@ ExecInitExprRec(Expr *node, ExprState *state,
|
||||
FmgrInfo *finfo;
|
||||
FunctionCallInfo fcinfo;
|
||||
AclResult aclresult;
|
||||
FmgrInfo *hash_finfo;
|
||||
FunctionCallInfo hash_fcinfo;
|
||||
Oid cmpfuncid;
|
||||
|
||||
/*
|
||||
@ -1262,18 +1260,6 @@ ExecInitExprRec(Expr *node, ExprState *state,
|
||||
*/
|
||||
if (OidIsValid(opexpr->hashfuncid))
|
||||
{
|
||||
hash_finfo = palloc0(sizeof(FmgrInfo));
|
||||
hash_fcinfo = palloc0(SizeForFunctionCallInfo(1));
|
||||
fmgr_info(opexpr->hashfuncid, hash_finfo);
|
||||
fmgr_info_set_expr((Node *) node, hash_finfo);
|
||||
InitFunctionCallInfoData(*hash_fcinfo, hash_finfo,
|
||||
1, opexpr->inputcollid, NULL,
|
||||
NULL);
|
||||
|
||||
scratch.d.hashedscalararrayop.hash_finfo = hash_finfo;
|
||||
scratch.d.hashedscalararrayop.hash_fcinfo_data = hash_fcinfo;
|
||||
scratch.d.hashedscalararrayop.hash_fn_addr = hash_finfo->fn_addr;
|
||||
|
||||
/* Evaluate scalar directly into left function argument */
|
||||
ExecInitExprRec(scalararg, state,
|
||||
&fcinfo->args[0].value, &fcinfo->args[0].isnull);
|
||||
@ -1292,11 +1278,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
|
||||
scratch.d.hashedscalararrayop.inclause = opexpr->useOr;
|
||||
scratch.d.hashedscalararrayop.finfo = finfo;
|
||||
scratch.d.hashedscalararrayop.fcinfo_data = fcinfo;
|
||||
scratch.d.hashedscalararrayop.fn_addr = finfo->fn_addr;
|
||||
scratch.d.hashedscalararrayop.saop = opexpr;
|
||||
|
||||
scratch.d.hashedscalararrayop.hash_finfo = hash_finfo;
|
||||
scratch.d.hashedscalararrayop.hash_fcinfo_data = hash_fcinfo;
|
||||
scratch.d.hashedscalararrayop.hash_fn_addr = hash_finfo->fn_addr;
|
||||
|
||||
ExprEvalPushStep(state, &scratch);
|
||||
}
|
||||
|
@ -217,6 +217,8 @@ typedef struct ScalarArrayOpExprHashTable
|
||||
{
|
||||
saophash_hash *hashtab; /* underlying hash table */
|
||||
struct ExprEvalStep *op;
|
||||
FmgrInfo hash_finfo; /* function's lookup data */
|
||||
FunctionCallInfoBaseData hash_fcinfo_data; /* arguments etc */
|
||||
} ScalarArrayOpExprHashTable;
|
||||
|
||||
/* Define parameters for ScalarArrayOpExpr hash table code generation. */
|
||||
@ -3474,13 +3476,13 @@ static uint32
|
||||
saop_element_hash(struct saophash_hash *tb, Datum key)
|
||||
{
|
||||
ScalarArrayOpExprHashTable *elements_tab = (ScalarArrayOpExprHashTable *) tb->private_data;
|
||||
FunctionCallInfo fcinfo = elements_tab->op->d.hashedscalararrayop.hash_fcinfo_data;
|
||||
FunctionCallInfo fcinfo = &elements_tab->hash_fcinfo_data;
|
||||
Datum hash;
|
||||
|
||||
fcinfo->args[0].value = key;
|
||||
fcinfo->args[0].isnull = false;
|
||||
|
||||
hash = elements_tab->op->d.hashedscalararrayop.hash_fn_addr(fcinfo);
|
||||
hash = elements_tab->hash_finfo.fn_addr(fcinfo);
|
||||
|
||||
return DatumGetUInt32(hash);
|
||||
}
|
||||
@ -3502,7 +3504,7 @@ saop_hash_element_match(struct saophash_hash *tb, Datum key1, Datum key2)
|
||||
fcinfo->args[1].value = key2;
|
||||
fcinfo->args[1].isnull = false;
|
||||
|
||||
result = elements_tab->op->d.hashedscalararrayop.fn_addr(fcinfo);
|
||||
result = elements_tab->op->d.hashedscalararrayop.finfo->fn_addr(fcinfo);
|
||||
|
||||
return DatumGetBool(result);
|
||||
}
|
||||
@ -3549,6 +3551,7 @@ ExecEvalHashedScalarArrayOp(ExprState *state, ExprEvalStep *op, ExprContext *eco
|
||||
/* Build the hash table on first evaluation */
|
||||
if (elements_tab == NULL)
|
||||
{
|
||||
ScalarArrayOpExpr *saop;
|
||||
int16 typlen;
|
||||
bool typbyval;
|
||||
char typalign;
|
||||
@ -3560,6 +3563,8 @@ ExecEvalHashedScalarArrayOp(ExprState *state, ExprEvalStep *op, ExprContext *eco
|
||||
MemoryContext oldcontext;
|
||||
ArrayType *arr;
|
||||
|
||||
saop = op->d.hashedscalararrayop.saop;
|
||||
|
||||
arr = DatumGetArrayTypeP(*op->resvalue);
|
||||
nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
|
||||
|
||||
@ -3571,10 +3576,21 @@ ExecEvalHashedScalarArrayOp(ExprState *state, ExprEvalStep *op, ExprContext *eco
|
||||
oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
|
||||
|
||||
elements_tab = (ScalarArrayOpExprHashTable *)
|
||||
palloc(sizeof(ScalarArrayOpExprHashTable));
|
||||
palloc0(offsetof(ScalarArrayOpExprHashTable, hash_fcinfo_data) +
|
||||
SizeForFunctionCallInfo(1));
|
||||
op->d.hashedscalararrayop.elements_tab = elements_tab;
|
||||
elements_tab->op = op;
|
||||
|
||||
fmgr_info(saop->hashfuncid, &elements_tab->hash_finfo);
|
||||
fmgr_info_set_expr((Node *) saop, &elements_tab->hash_finfo);
|
||||
|
||||
InitFunctionCallInfoData(elements_tab->hash_fcinfo_data,
|
||||
&elements_tab->hash_finfo,
|
||||
1,
|
||||
saop->inputcollid,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/*
|
||||
* Create the hash table sizing it according to the number of elements
|
||||
* in the array. This does assume that the array has no duplicates.
|
||||
@ -3669,7 +3685,7 @@ ExecEvalHashedScalarArrayOp(ExprState *state, ExprEvalStep *op, ExprContext *eco
|
||||
fcinfo->args[1].value = (Datum) 0;
|
||||
fcinfo->args[1].isnull = true;
|
||||
|
||||
result = op->d.hashedscalararrayop.fn_addr(fcinfo);
|
||||
result = op->d.hashedscalararrayop.finfo->fn_addr(fcinfo);
|
||||
resultnull = fcinfo->isnull;
|
||||
|
||||
/*
|
||||
|
@ -584,12 +584,7 @@ typedef struct ExprEvalStep
|
||||
struct ScalarArrayOpExprHashTable *elements_tab;
|
||||
FmgrInfo *finfo; /* function's lookup data */
|
||||
FunctionCallInfo fcinfo_data; /* arguments etc */
|
||||
/* faster to access without additional indirection: */
|
||||
PGFunction fn_addr; /* actual call address */
|
||||
FmgrInfo *hash_finfo; /* function's lookup data */
|
||||
FunctionCallInfo hash_fcinfo_data; /* arguments etc */
|
||||
/* faster to access without additional indirection: */
|
||||
PGFunction hash_fn_addr; /* actual call address */
|
||||
ScalarArrayOpExpr *saop;
|
||||
} hashedscalararrayop;
|
||||
|
||||
/* for EEOP_XMLEXPR */
|
||||
|
Loading…
Reference in New Issue
Block a user