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は省略する。