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

Commite6336b8

Browse files
committed
Save a few cycles in advance_transition_function().
Keep a pre-initialized FunctionCallInfoData in AggStatePerAggData, andre-use that at each row instead of doing InitFunctionCallInfoData eachtime. This saves only half a dozen assignments and maybe some stackmanipulation, and yet that seems to be good for a percent or two of theoverall query run time for simple aggregates such as count(*). The costis that the FunctionCallInfoData (which is about a kilobyte, on 64-bitmachines) stays allocated for the duration of the query instead of beingshort-lived stack data. But we're already paying an equivalent space costfor each regular FuncExpr or OpExpr node, so I don't feel bad about payingit for aggregate functions. The code seems a little cleaner this way too,since the number of things passed to advance_transition_function decreases.
1 parentd59ff6c commite6336b8

File tree

1 file changed

+38
-27
lines changed

1 file changed

+38
-27
lines changed

‎src/backend/executor/nodeAgg.c

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,14 @@ typedef struct AggStatePerAggData
235235
*/
236236

237237
Tuplesortstate*sortstate;/* sort object, if DISTINCT or ORDER BY */
238+
239+
/*
240+
* This field is a pre-initialized FunctionCallInfo struct used for
241+
* calling this aggregate's transfn. We save a few cycles per row by not
242+
* re-initializing the unchanging fields; which isn't much, but it seems
243+
* worth the extra space consumption.
244+
*/
245+
FunctionCallInfoDatatransfn_fcinfo;
238246
}AggStatePerAggData;
239247

240248
/*
@@ -290,8 +298,7 @@ static void initialize_aggregates(AggState *aggstate,
290298
AggStatePerGrouppergroup);
291299
staticvoidadvance_transition_function(AggState*aggstate,
292300
AggStatePerAggperaggstate,
293-
AggStatePerGrouppergroupstate,
294-
FunctionCallInfoData*fcinfo);
301+
AggStatePerGrouppergroupstate);
295302
staticvoidadvance_aggregates(AggState*aggstate,AggStatePerGrouppergroup);
296303
staticvoidprocess_ordered_aggregate_single(AggState*aggstate,
297304
AggStatePerAggperaggstate,
@@ -399,28 +406,30 @@ initialize_aggregates(AggState *aggstate,
399406
* Given new input value(s), advance the transition function of an aggregate.
400407
*
401408
* The new values (and null flags) have been preloaded into argument positions
402-
* 1 and up in fcinfo, so that we needn't copy them again to pass to the
403-
* transition function. No other fields of fcinfo are assumed valid.
409+
* 1 and up in peraggstate->transfn_fcinfo, so that we needn't copy them again
410+
* to pass to the transition function.We also expect that the static fields
411+
* of the fcinfo are already initialized; that was done by ExecInitAgg().
404412
*
405413
* It doesn't matter which memory context this is called in.
406414
*/
407415
staticvoid
408416
advance_transition_function(AggState*aggstate,
409417
AggStatePerAggperaggstate,
410-
AggStatePerGrouppergroupstate,
411-
FunctionCallInfoData*fcinfo)
418+
AggStatePerGrouppergroupstate)
412419
{
413-
intnumTransInputs=peraggstate->numTransInputs;
420+
FunctionCallInfofcinfo=&peraggstate->transfn_fcinfo;
414421
MemoryContextoldContext;
415422
DatumnewVal;
416-
inti;
417423

418424
if (peraggstate->transfn.fn_strict)
419425
{
420426
/*
421427
* For a strict transfn, nothing happens when there's a NULL input; we
422428
* just keep the prior transValue.
423429
*/
430+
intnumTransInputs=peraggstate->numTransInputs;
431+
inti;
432+
424433
for (i=1;i <=numTransInputs;i++)
425434
{
426435
if (fcinfo->argnull[i])
@@ -467,12 +476,9 @@ advance_transition_function(AggState *aggstate,
467476
/*
468477
* OK to call the transition function
469478
*/
470-
InitFunctionCallInfoData(*fcinfo,&(peraggstate->transfn),
471-
numTransInputs+1,
472-
peraggstate->aggCollation,
473-
(void*)aggstate,NULL);
474479
fcinfo->arg[0]=pergroupstate->transValue;
475480
fcinfo->argnull[0]=pergroupstate->transValueIsNull;
481+
fcinfo->isnull= false;/* just in case transfn doesn't set it */
476482

477483
newVal=FunctionCallInvoke(fcinfo);
478484

@@ -574,19 +580,18 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
574580
else
575581
{
576582
/* We can apply the transition function immediately */
577-
FunctionCallInfoDatafcinfo;
583+
FunctionCallInfofcinfo=&peraggstate->transfn_fcinfo;
578584

579585
/* Load values into fcinfo */
580586
/* Start from 1, since the 0th arg will be the transition value */
581587
Assert(slot->tts_nvalid >=numTransInputs);
582588
for (i=0;i<numTransInputs;i++)
583589
{
584-
fcinfo.arg[i+1]=slot->tts_values[i];
585-
fcinfo.argnull[i+1]=slot->tts_isnull[i];
590+
fcinfo->arg[i+1]=slot->tts_values[i];
591+
fcinfo->argnull[i+1]=slot->tts_isnull[i];
586592
}
587593

588-
advance_transition_function(aggstate,peraggstate,pergroupstate,
589-
&fcinfo);
594+
advance_transition_function(aggstate,peraggstate,pergroupstate);
590595
}
591596
}
592597
}
@@ -622,17 +627,17 @@ process_ordered_aggregate_single(AggState *aggstate,
622627
MemoryContextworkcontext=aggstate->tmpcontext->ecxt_per_tuple_memory;
623628
MemoryContextoldContext;
624629
boolisDistinct= (peraggstate->numDistinctCols>0);
630+
FunctionCallInfofcinfo=&peraggstate->transfn_fcinfo;
625631
Datum*newVal;
626632
bool*isNull;
627-
FunctionCallInfoDatafcinfo;
628633

629634
Assert(peraggstate->numDistinctCols<2);
630635

631636
tuplesort_performsort(peraggstate->sortstate);
632637

633638
/* Load the column into argument 1 (arg 0 will be transition value) */
634-
newVal=fcinfo.arg+1;
635-
isNull=fcinfo.argnull+1;
639+
newVal=fcinfo->arg+1;
640+
isNull=fcinfo->argnull+1;
636641

637642
/*
638643
* Note: if input type is pass-by-ref, the datums returned by the sort are
@@ -668,8 +673,7 @@ process_ordered_aggregate_single(AggState *aggstate,
668673
}
669674
else
670675
{
671-
advance_transition_function(aggstate,peraggstate,pergroupstate,
672-
&fcinfo);
676+
advance_transition_function(aggstate,peraggstate,pergroupstate);
673677
/* forget the old value, if any */
674678
if (!oldIsNull&& !peraggstate->inputtypeByVal)
675679
pfree(DatumGetPointer(oldVal));
@@ -704,7 +708,7 @@ process_ordered_aggregate_multi(AggState *aggstate,
704708
AggStatePerGrouppergroupstate)
705709
{
706710
MemoryContextworkcontext=aggstate->tmpcontext->ecxt_per_tuple_memory;
707-
FunctionCallInfoDatafcinfo;
711+
FunctionCallInfofcinfo=&peraggstate->transfn_fcinfo;
708712
TupleTableSlot*slot1=peraggstate->evalslot;
709713
TupleTableSlot*slot2=peraggstate->uniqslot;
710714
intnumTransInputs=peraggstate->numTransInputs;
@@ -739,12 +743,11 @@ process_ordered_aggregate_multi(AggState *aggstate,
739743
/* Start from 1, since the 0th arg will be the transition value */
740744
for (i=0;i<numTransInputs;i++)
741745
{
742-
fcinfo.arg[i+1]=slot1->tts_values[i];
743-
fcinfo.argnull[i+1]=slot1->tts_isnull[i];
746+
fcinfo->arg[i+1]=slot1->tts_values[i];
747+
fcinfo->argnull[i+1]=slot1->tts_isnull[i];
744748
}
745749

746-
advance_transition_function(aggstate,peraggstate,pergroupstate,
747-
&fcinfo);
750+
advance_transition_function(aggstate,peraggstate,pergroupstate);
748751

749752
if (numDistinctCols>0)
750753
{
@@ -1799,6 +1802,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
17991802
&transfnexpr,
18001803
&finalfnexpr);
18011804

1805+
/* set up infrastructure for calling the transfn and finalfn */
18021806
fmgr_info(transfn_oid,&peraggstate->transfn);
18031807
fmgr_info_set_expr((Node*)transfnexpr,&peraggstate->transfn);
18041808

@@ -1810,6 +1814,13 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
18101814

18111815
peraggstate->aggCollation=aggref->inputcollid;
18121816

1817+
InitFunctionCallInfoData(peraggstate->transfn_fcinfo,
1818+
&peraggstate->transfn,
1819+
peraggstate->numTransInputs+1,
1820+
peraggstate->aggCollation,
1821+
(void*)aggstate,NULL);
1822+
1823+
/* get info about relevant datatypes */
18131824
get_typlenbyval(aggref->aggtype,
18141825
&peraggstate->resulttypeLen,
18151826
&peraggstate->resulttypeByVal);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp