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

Commit 2742c45

Browse files
committed
expression eval: Reduce number of steps for agg transition invocations.
Do so by combining the various steps that are part of aggregate transition function invocation into one larger step. As some of the current steps are only necessary for some aggregates, have one variant of the aggregate transition step for each possible combination. To avoid further manual copies of code in the different transition step implementations, move most of the code into helper functions marked as "always inline". The benefit of this change is an increase in performance when aggregating lots of rows. This comes in part due to the reduced number of indirect jumps due to the reduced number of steps, and in part by reducing redundant setup code across steps. This mainly benefits interpreted execution, but the code generated by JIT is also improved a bit. As a nice side-effect it also ends up making the code a bit simpler. A small additional optimization is removing the need to set aggstate->curaggcontext before calling ExecAggInitGroup, choosing to instead passign curaggcontext as an argument. It was, in contrast to other aggregate related functions, only needed to fetch a memory context to copy the transition value into. Author: Andres Freund Discussion: https://postgr.es/m/20191023163849.sosqbfs5yenocez3@alap3.anarazel.de https://postgr.es/m/5c371df7cee903e8cd4c685f90c6c72086d3a2dc.camel@j-davis.com
1 parent 7d672b7 commit 2742c45

File tree

5 files changed

+332
-348
lines changed

5 files changed

+332
-348
lines changed

src/backend/executor/execExpr.c

+48-57
Original file line numberDiff line numberDiff line change
@@ -3229,8 +3229,6 @@ ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
32293229
FunctionCallInfo fcinfo, AggStatePerTrans pertrans,
32303230
int transno, int setno, int setoff, bool ishash)
32313231
{
3232-
int adjust_init_jumpnull = -1;
3233-
int adjust_strict_jumpnull = -1;
32343232
ExprContext *aggcontext;
32353233

32363234
if (ishash)
@@ -3239,52 +3237,61 @@ ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
32393237
aggcontext = aggstate->aggcontexts[setno];
32403238

32413239
/*
3240+
* Determine appropriate transition implementation.
3241+
*
3242+
* For non-ordered aggregates:
3243+
*
32423244
* If the initial value for the transition state doesn't exist in the
32433245
* pg_aggregate table then we will let the first non-NULL value returned
32443246
* from the outer procNode become the initial value. (This is useful for
32453247
* aggregates like max() and min().) The noTransValue flag signals that we
3246-
* still need to do this.
3248+
* need to do so. If true, generate a
3249+
* EEOP_AGG_INIT_STRICT_PLAIN_TRANS{,_BYVAL} step. This step also needs to
3250+
* do the work described next:
3251+
*
3252+
* If the function is strict, but does have an initial value, choose
3253+
* EEOP_AGG_STRICT_PLAIN_TRANS{,_BYVAL}, which skips the transition
3254+
* function if the transition value has become NULL (because a previous
3255+
* transition function returned NULL). This step also needs to do the work
3256+
* described next:
3257+
*
3258+
* Otherwise we call EEOP_AGG_PLAIN_TRANS{,_BYVAL}, which does not have to
3259+
* perform either of the above checks.
3260+
*
3261+
* Having steps with overlapping responsibilities is not nice, but
3262+
* aggregations are very performance sensitive, making this worthwhile.
3263+
*
3264+
* For ordered aggregates:
3265+
*
3266+
* Only need to choose between the faster path for a single orderred
3267+
* column, and the one between multiple columns. Checking strictness etc
3268+
* is done when finalizing the aggregate. See
3269+
* process_ordered_aggregate_{single, multi} and
3270+
* advance_transition_function.
32473271
*/
3248-
if (pertrans->numSortCols == 0 &&
3249-
fcinfo->flinfo->fn_strict &&
3250-
pertrans->initValueIsNull)
3251-
{
3252-
scratch->opcode = EEOP_AGG_INIT_TRANS;
3253-
scratch->d.agg_init_trans.pertrans = pertrans;
3254-
scratch->d.agg_init_trans.setno = setno;
3255-
scratch->d.agg_init_trans.setoff = setoff;
3256-
scratch->d.agg_init_trans.transno = transno;
3257-
scratch->d.agg_init_trans.aggcontext = aggcontext;
3258-
scratch->d.agg_init_trans.jumpnull = -1; /* adjust later */
3259-
ExprEvalPushStep(state, scratch);
3260-
3261-
/* see comment about jumping out below */
3262-
adjust_init_jumpnull = state->steps_len - 1;
3263-
}
3264-
3265-
if (pertrans->numSortCols == 0 &&
3266-
fcinfo->flinfo->fn_strict)
3272+
if (pertrans->numSortCols == 0)
32673273
{
3268-
scratch->opcode = EEOP_AGG_STRICT_TRANS_CHECK;
3269-
scratch->d.agg_strict_trans_check.setno = setno;
3270-
scratch->d.agg_strict_trans_check.setoff = setoff;
3271-
scratch->d.agg_strict_trans_check.transno = transno;
3272-
scratch->d.agg_strict_trans_check.jumpnull = -1; /* adjust later */
3273-
ExprEvalPushStep(state, scratch);
3274-
3275-
/*
3276-
* Note, we don't push into adjust_bailout here - those jump to the
3277-
* end of all transition value computations. Here a single transition
3278-
* value is NULL, so just skip processing the individual value.
3279-
*/
3280-
adjust_strict_jumpnull = state->steps_len - 1;
3274+
if (pertrans->transtypeByVal)
3275+
{
3276+
if (fcinfo->flinfo->fn_strict &&
3277+
pertrans->initValueIsNull)
3278+
scratch->opcode = EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL;
3279+
else if (fcinfo->flinfo->fn_strict)
3280+
scratch->opcode = EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL;
3281+
else
3282+
scratch->opcode = EEOP_AGG_PLAIN_TRANS_BYVAL;
3283+
}
3284+
else
3285+
{
3286+
if (fcinfo->flinfo->fn_strict &&
3287+
pertrans->initValueIsNull)
3288+
scratch->opcode = EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF;
3289+
else if (fcinfo->flinfo->fn_strict)
3290+
scratch->opcode = EEOP_AGG_PLAIN_TRANS_STRICT_BYREF;
3291+
else
3292+
scratch->opcode = EEOP_AGG_PLAIN_TRANS_BYREF;
3293+
}
32813294
}
3282-
3283-
/* invoke appropriate transition implementation */
3284-
if (pertrans->numSortCols == 0 && pertrans->transtypeByVal)
3285-
scratch->opcode = EEOP_AGG_PLAIN_TRANS_BYVAL;
3286-
else if (pertrans->numSortCols == 0)
3287-
scratch->opcode = EEOP_AGG_PLAIN_TRANS;
32883295
else if (pertrans->numInputs == 1)
32893296
scratch->opcode = EEOP_AGG_ORDERED_TRANS_DATUM;
32903297
else
@@ -3296,22 +3303,6 @@ ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
32963303
scratch->d.agg_trans.transno = transno;
32973304
scratch->d.agg_trans.aggcontext = aggcontext;
32983305
ExprEvalPushStep(state, scratch);
3299-
3300-
/* adjust jumps so they jump till after transition invocation */
3301-
if (adjust_init_jumpnull != -1)
3302-
{
3303-
ExprEvalStep *as = &state->steps[adjust_init_jumpnull];
3304-
3305-
Assert(as->d.agg_init_trans.jumpnull == -1);
3306-
as->d.agg_init_trans.jumpnull = state->steps_len;
3307-
}
3308-
if (adjust_strict_jumpnull != -1)
3309-
{
3310-
ExprEvalStep *as = &state->steps[adjust_strict_jumpnull];
3311-
3312-
Assert(as->d.agg_strict_trans_check.jumpnull == -1);
3313-
as->d.agg_strict_trans_check.jumpnull = state->steps_len;
3314-
}
33153306
}
33163307

33173308
/*

0 commit comments

Comments
 (0)