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

Commitd35d32d

Browse files
Add special case fast-paths for strict functions
Many STRICT function calls will have one or two arguments, in whichcase we can speed up checking for NULL input by avoiding setting upa loop over the arguments. This adds EEOP_FUNCEXPR_STRICT_1 and thecorresponding EEOP_FUNCEXPR_STRICT_2 for functions with one and twoarguments respectively.Author: Andres Freund <andres@anarazel.de>Co-authored-by: Daniel Gustafsson <daniel@yesql.se>Reviewed-by: Andreas Karlsson <andreas@proxel.se>Discussion:https://postgr.es/m/415721CE-7D2E-4B74-B5D9-1950083BA03E@yesql.seDiscussion:https://postgr.es/m/20191023163849.sosqbfs5yenocez3@alap3.anarazel.de
1 parent8dd7c7c commitd35d32d

File tree

4 files changed

+96
-5
lines changed

4 files changed

+96
-5
lines changed

‎src/backend/executor/execExpr.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2788,7 +2788,15 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
27882788
if (pgstat_track_functions <=flinfo->fn_stats)
27892789
{
27902790
if (flinfo->fn_strict&&nargs>0)
2791-
scratch->opcode=EEOP_FUNCEXPR_STRICT;
2791+
{
2792+
/* Choose nargs optimized implementation if available. */
2793+
if (nargs==1)
2794+
scratch->opcode=EEOP_FUNCEXPR_STRICT_1;
2795+
elseif (nargs==2)
2796+
scratch->opcode=EEOP_FUNCEXPR_STRICT_2;
2797+
else
2798+
scratch->opcode=EEOP_FUNCEXPR_STRICT;
2799+
}
27922800
else
27932801
scratch->opcode=EEOP_FUNCEXPR;
27942802
}
@@ -3892,6 +3900,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
38923900
{
38933901
if (strictnulls)
38943902
scratch.opcode=EEOP_AGG_STRICT_INPUT_CHECK_NULLS;
3903+
elseif (strictargs&&pertrans->numTransInputs==1)
3904+
scratch.opcode=EEOP_AGG_STRICT_INPUT_CHECK_ARGS_1;
38953905
else
38963906
scratch.opcode=EEOP_AGG_STRICT_INPUT_CHECK_ARGS;
38973907
scratch.d.agg_strict_input_check.nulls=strictnulls;
@@ -3968,6 +3978,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
39683978
as->d.jump.jumpdone=state->steps_len;
39693979
}
39703980
elseif (as->opcode==EEOP_AGG_STRICT_INPUT_CHECK_ARGS||
3981+
as->opcode==EEOP_AGG_STRICT_INPUT_CHECK_ARGS_1||
39713982
as->opcode==EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
39723983
{
39733984
Assert(as->d.agg_strict_input_check.jumpnull==-1);

‎src/backend/executor/execExprInterp.c

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,9 @@ ExecReadyInterpretedExpr(ExprState *state)
366366
return;
367367
}
368368
elseif (step0==EEOP_CASE_TESTVAL&&
369-
step1==EEOP_FUNCEXPR_STRICT)
369+
(step1==EEOP_FUNCEXPR_STRICT||
370+
step1==EEOP_FUNCEXPR_STRICT_1||
371+
step1==EEOP_FUNCEXPR_STRICT_2))
370372
{
371373
state->evalfunc_private=ExecJustApplyFuncToCase;
372374
return;
@@ -498,6 +500,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
498500
&&CASE_EEOP_CONST,
499501
&&CASE_EEOP_FUNCEXPR,
500502
&&CASE_EEOP_FUNCEXPR_STRICT,
503+
&&CASE_EEOP_FUNCEXPR_STRICT_1,
504+
&&CASE_EEOP_FUNCEXPR_STRICT_2,
501505
&&CASE_EEOP_FUNCEXPR_FUSAGE,
502506
&&CASE_EEOP_FUNCEXPR_STRICT_FUSAGE,
503507
&&CASE_EEOP_BOOL_AND_STEP_FIRST,
@@ -575,6 +579,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
575579
&&CASE_EEOP_AGG_STRICT_DESERIALIZE,
576580
&&CASE_EEOP_AGG_DESERIALIZE,
577581
&&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
582+
&&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS_1,
578583
&&CASE_EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
579584
&&CASE_EEOP_AGG_PLAIN_PERGROUP_NULLCHECK,
580585
&&CASE_EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL,
@@ -925,13 +930,16 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
925930
EEO_NEXT();
926931
}
927932

933+
/* strict function call with more than two arguments */
928934
EEO_CASE(EEOP_FUNCEXPR_STRICT)
929935
{
930936
FunctionCallInfofcinfo=op->d.func.fcinfo_data;
931937
NullableDatum*args=fcinfo->args;
932938
intnargs=op->d.func.nargs;
933939
Datumd;
934940

941+
Assert(nargs>2);
942+
935943
/* strict function, so check for NULL args */
936944
for (intargno=0;argno<nargs;argno++)
937945
{
@@ -950,6 +958,54 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
950958
EEO_NEXT();
951959
}
952960

961+
/* strict function call with one argument */
962+
EEO_CASE(EEOP_FUNCEXPR_STRICT_1)
963+
{
964+
FunctionCallInfofcinfo=op->d.func.fcinfo_data;
965+
NullableDatum*args=fcinfo->args;
966+
967+
Assert(op->d.func.nargs==1);
968+
969+
/* strict function, so check for NULL args */
970+
if (args[0].isnull)
971+
*op->resnull= true;
972+
else
973+
{
974+
Datumd;
975+
976+
fcinfo->isnull= false;
977+
d=op->d.func.fn_addr(fcinfo);
978+
*op->resvalue=d;
979+
*op->resnull=fcinfo->isnull;
980+
}
981+
982+
EEO_NEXT();
983+
}
984+
985+
/* strict function call with two arguments */
986+
EEO_CASE(EEOP_FUNCEXPR_STRICT_2)
987+
{
988+
FunctionCallInfofcinfo=op->d.func.fcinfo_data;
989+
NullableDatum*args=fcinfo->args;
990+
991+
Assert(op->d.func.nargs==2);
992+
993+
/* strict function, so check for NULL args */
994+
if (args[0].isnull||args[1].isnull)
995+
*op->resnull= true;
996+
else
997+
{
998+
Datumd;
999+
1000+
fcinfo->isnull= false;
1001+
d=op->d.func.fn_addr(fcinfo);
1002+
*op->resvalue=d;
1003+
*op->resnull=fcinfo->isnull;
1004+
}
1005+
1006+
EEO_NEXT();
1007+
}
1008+
9531009
EEO_CASE(EEOP_FUNCEXPR_FUSAGE)
9541010
{
9551011
/* not common enough to inline */
@@ -1982,11 +2038,14 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
19822038
* input is not NULL.
19832039
*/
19842040

2041+
/* when checking more than one argument */
19852042
EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_ARGS)
19862043
{
19872044
NullableDatum*args=op->d.agg_strict_input_check.args;
19882045
intnargs=op->d.agg_strict_input_check.nargs;
19892046

2047+
Assert(nargs>1);
2048+
19902049
for (intargno=0;argno<nargs;argno++)
19912050
{
19922051
if (args[argno].isnull)
@@ -1995,6 +2054,19 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
19952054
EEO_NEXT();
19962055
}
19972056

2057+
/* special case for just one argument */
2058+
EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_ARGS_1)
2059+
{
2060+
NullableDatum*args=op->d.agg_strict_input_check.args;
2061+
PG_USED_FOR_ASSERTS_ONLYintnargs=op->d.agg_strict_input_check.nargs;
2062+
2063+
Assert(nargs==1);
2064+
2065+
if (args[0].isnull)
2066+
EEO_JUMP(op->d.agg_strict_input_check.jumpnull);
2067+
EEO_NEXT();
2068+
}
2069+
19982070
EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
19992071
{
20002072
bool*nulls=op->d.agg_strict_input_check.nulls;

‎src/backend/jit/llvm/llvmjit_expr.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,12 +662,16 @@ llvm_compile_expr(ExprState *state)
662662

663663
caseEEOP_FUNCEXPR:
664664
caseEEOP_FUNCEXPR_STRICT:
665+
caseEEOP_FUNCEXPR_STRICT_1:
666+
caseEEOP_FUNCEXPR_STRICT_2:
665667
{
666668
FunctionCallInfofcinfo=op->d.func.fcinfo_data;
667669
LLVMValueRefv_fcinfo_isnull;
668670
LLVMValueRefv_retval;
669671

670-
if (opcode==EEOP_FUNCEXPR_STRICT)
672+
if (opcode==EEOP_FUNCEXPR_STRICT||
673+
opcode==EEOP_FUNCEXPR_STRICT_1||
674+
opcode==EEOP_FUNCEXPR_STRICT_2)
671675
{
672676
LLVMBasicBlockRefb_nonull;
673677
LLVMBasicBlockRef*b_checkargnulls;
@@ -2482,6 +2486,7 @@ llvm_compile_expr(ExprState *state)
24822486
}
24832487

24842488
caseEEOP_AGG_STRICT_INPUT_CHECK_ARGS:
2489+
caseEEOP_AGG_STRICT_INPUT_CHECK_ARGS_1:
24852490
caseEEOP_AGG_STRICT_INPUT_CHECK_NULLS:
24862491
{
24872492
intnargs=op->d.agg_strict_input_check.nargs;

‎src/include/executor/execExpr.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,13 @@ typedef enum ExprEvalOp
116116

117117
/*
118118
* Evaluate function call (including OpExprs etc). For speed, we
119-
* distinguish in the opcode whether the function is strictand/or
120-
* requires usage stats tracking.
119+
* distinguish in the opcode whether the function is strictwith 1, 2,or
120+
*more arguments and/orrequires usage stats tracking.
121121
*/
122122
EEOP_FUNCEXPR,
123123
EEOP_FUNCEXPR_STRICT,
124+
EEOP_FUNCEXPR_STRICT_1,
125+
EEOP_FUNCEXPR_STRICT_2,
124126
EEOP_FUNCEXPR_FUSAGE,
125127
EEOP_FUNCEXPR_STRICT_FUSAGE,
126128

@@ -276,6 +278,7 @@ typedef enum ExprEvalOp
276278
EEOP_AGG_STRICT_DESERIALIZE,
277279
EEOP_AGG_DESERIALIZE,
278280
EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
281+
EEOP_AGG_STRICT_INPUT_CHECK_ARGS_1,
279282
EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
280283
EEOP_AGG_PLAIN_PERGROUP_NULLCHECK,
281284
EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp