sum(int4)の高速化
backend/utils/adt/numeric.cのint4_sumで、
Datum int4_sum(PG_FUNCTION_ARGS) { int64 newval; if (PG_ARGISNULL(0)) { /* No non-null input seen so far... */ if (PG_ARGISNULL(1)) PG_RETURN_NULL(); /* still no non-null */ /* This is the first non-null input. */ newval = (int64) PG_GETARG_INT32(1); PG_RETURN_INT64(newval); }
これを、
Datum int4_sum(PG_FUNCTION_ARGS) { int64 newval; if (PG_ARGISNULL(0)) { /* No non-null input seen so far... */ if (PG_ARGISNULL(1)) PG_RETURN_NULL(); /* still no non-null */ /* This is the first non-null input. */ newval = (int64) PG_GETARG_INT32(1); if (fcinfo->context && IsA(fcinfo->context, AggState)) { AggState aggstate = (AggState)fcinfo->context; /* * Contextをaggstate->aggcontextに切り替えて * int64データを作成し、returnする */ } else PG_RETURN_INT64(newval); }
こんな感じにすれば、AllocSetResetの負荷が下がって高速化されるはず。
この変更を行う場合、nodeAgg.cのadvance_transition_functionも変更する。
if (!peraggstate->transtypeByVal && DatumGetPointer(newVal) != DatumGetPointer(pergroupstate->transValue)) { if (!fcinfo.isnull) { MemoryContextSwitchTo(aggstate->aggcontext); newVal = datumCopy(newVal, peraggstate->transtypeByVal, peraggstate->transtypeLen); } if (!pergroupstate->transValueIsNull) pfree(DatumGetPointer(pergroupstate->transValue)); }
newValがaggstate->aggcontextから取得されているか調べて、そうだったらdatumCopyは省略する。