Re: [PATCHES] avg(int2) and avg(int8) micro-opt

2005-04-06 Thread Neil Conway
Neil Conway wrote:
Attached is a patch that applies the same optimization to int2_sum(), 
int4_sum(), float4_accum(), and float8_accum(). It wasn't possible to 
optimize do_numeric_accum() or int8_sum() since they both use numerics. 
Applied.
-Neil
---(end of broadcast)---
TIP 9: the planner will ignore your desire to choose an index scan if your
 joining column's datatypes do not match


Re: [PATCHES] avg(int2) and avg(int8) micro-opt

2005-04-06 Thread Neil Conway
Neil Conway wrote:
Yeah, there might be some others we could improve. float4_accum() and 
float8_accum() look like they could be improved pretty easily, and 
do_numeric_accum() should also be fixable with some hackery. I suppose 
it's also worth optimizing int2_sum(), int4_sum() and int8_sum().
Attached is a patch that applies the same optimization to int2_sum(), 
int4_sum(), float4_accum(), and float8_accum(). It wasn't possible to 
optimize do_numeric_accum() or int8_sum() since they both use numerics. 
Performance gains are similar to those measured when this optimization 
has been applied to similar aggregates (e.g. avg(float8) goes from about 
6400 ms to about 4300 ms on my machine, for a single column of float8 
and about 1 million rows).

Barring any objections, I'll apply this to HEAD tomorrow.
-Neil
Index: src/backend/utils/adt/float.c
===
RCS file: /Users/neilc/local/cvs/pgsql/src/backend/utils/adt/float.c,v
retrieving revision 1.113
diff -c -r1.113 float.c
*** src/backend/utils/adt/float.c	11 Feb 2005 04:08:58 -	1.113
--- src/backend/utils/adt/float.c	6 Apr 2005 07:24:38 -
***
*** 1902,1909 
  	float8		N,
  sumX,
  sumX2;
- 	Datum		transdatums[3];
- 	ArrayType  *result;
  
  	transvalues = check_float8_array(transarray, "float8_accum");
  	N = transvalues[0];
--- 1902,1907 
***
*** 1914,1928 
  	sumX += newval;
  	sumX2 += newval * newval;
  
! 	transdatums[0] = Float8GetDatumFast(N);
! 	transdatums[1] = Float8GetDatumFast(sumX);
! 	transdatums[2] = Float8GetDatumFast(sumX2);
! 
! 	result = construct_array(transdatums, 3,
! 			 FLOAT8OID,
! 		 sizeof(float8), false /* float8 byval */ , 'd');
  
! 	PG_RETURN_ARRAYTYPE_P(result);
  }
  
  Datum
--- 1912,1946 
  	sumX += newval;
  	sumX2 += newval * newval;
  
! 	/*
! 	 * If we're invoked by nodeAgg, we can cheat and modify our first
! 	 * parameter in-place to reduce palloc overhead. Otherwise we
! 	 * construct a new array with the updated transition data and
! 	 * return it.
! 	 */
! 	if (fcinfo->context && IsA(fcinfo->context, AggState))
! 	{
! 		transvalues[0] = N;
! 		transvalues[1] = sumX;
! 		transvalues[2] = sumX2;
! 
! 		PG_RETURN_ARRAYTYPE_P(transarray);
! 	}
! 	else
! 	{
! 		Datum		transdatums[3];
! 		ArrayType  *result;
! 
! 		transdatums[0] = Float8GetDatumFast(N);
! 		transdatums[1] = Float8GetDatumFast(sumX);
! 		transdatums[2] = Float8GetDatumFast(sumX2);
! 
! 		result = construct_array(transdatums, 3,
!  FLOAT8OID,
!  sizeof(float8), false /* float8 byval */ , 'd');
  
! 		PG_RETURN_ARRAYTYPE_P(result);
! 	}
  }
  
  Datum
***
*** 1935,1942 
  sumX,
  sumX2,
  newval;
- 	Datum		transdatums[3];
- 	ArrayType  *result;
  
  	transvalues = check_float8_array(transarray, "float4_accum");
  	N = transvalues[0];
--- 1953,1958 
***
*** 1950,1964 
  	sumX += newval;
  	sumX2 += newval * newval;
  
! 	transdatums[0] = Float8GetDatumFast(N);
! 	transdatums[1] = Float8GetDatumFast(sumX);
! 	transdatums[2] = Float8GetDatumFast(sumX2);
! 
! 	result = construct_array(transdatums, 3,
! 			 FLOAT8OID,
! 		 sizeof(float8), false /* float8 byval */ , 'd');
  
! 	PG_RETURN_ARRAYTYPE_P(result);
  }
  
  Datum
--- 1966,2000 
  	sumX += newval;
  	sumX2 += newval * newval;
  
! 	/*
! 	 * If we're invoked by nodeAgg, we can cheat and modify our first
! 	 * parameter in-place to reduce palloc overhead. Otherwise we
! 	 * construct a new array with the updated transition data and
! 	 * return it.
! 	 */
! 	if (fcinfo->context && IsA(fcinfo->context, AggState))
! 	{
! 		transvalues[0] = N;
! 		transvalues[1] = sumX;
! 		transvalues[2] = sumX2;
! 
! 		PG_RETURN_ARRAYTYPE_P(transarray);
! 	}
! 	else
! 	{
! 		Datum		transdatums[3];
! 		ArrayType  *result;
! 
! 		transdatums[0] = Float8GetDatumFast(N);
! 		transdatums[1] = Float8GetDatumFast(sumX);
! 		transdatums[2] = Float8GetDatumFast(sumX2);
! 
! 		result = construct_array(transdatums, 3,
!  FLOAT8OID,
!  sizeof(float8), false /* float8 byval */ , 'd');
  
! 		PG_RETURN_ARRAYTYPE_P(result);
! 	}
  }
  
  Datum
Index: src/backend/utils/adt/numeric.c
===
RCS file: /Users/neilc/local/cvs/pgsql/src/backend/utils/adt/numeric.c,v
retrieving revision 1.82
diff -c -r1.82 numeric.c
*** src/backend/utils/adt/numeric.c	4 Apr 2005 23:50:27 -	1.82
--- src/backend/utils/adt/numeric.c	6 Apr 2005 08:07:37 -
***
*** 2357,2363 
  Datum
  int2_sum(PG_FUNCTION_ARGS)
  {
- 	int64		oldsum;
  	int64		newval;
  
  	if (PG_ARGISNULL(0))
--- 2357,2362 
***
*** 2370,2391 
  		PG_RETURN_INT64(newval);
  	}
  
! 	oldsum = PG_GETARG_INT64(0);
  
! 	/* Leave sum unchanged if new input is null. */
! 	if (PG_ARGISNULL(1))
! 		PG_RETURN_INT64(oldsum);
  
! 	/* OK to do the addition. */
! 	newval = oldsum + (int64) PG_G

Re: [PATCHES] avg(int2) and avg(int8) micro-opt

2005-04-04 Thread Tom Lane
Neil Conway <[EMAIL PROTECTED]> writes:
> Tom Lane wrote:
>> Why only those two?  Might as well make all the accum functions look alike.

> Yeah, there might be some others we could improve. float4_accum() and 
> float8_accum() look like they could be improved pretty easily, and 
> do_numeric_accum() should also be fixable with some hackery. I suppose 
> it's also worth optimizing int2_sum(), int4_sum() and int8_sum(). I'll 
> send a patch for this later today or tomorrow. Are there any other 
> transition functions where we can apply this technique?

Actually, do_numeric_accum can't be fixed easily because numeric is a
varlena type.  The basic requirement for this hack is that the size of
the transition value be constant ...

regards, tom lane

---(end of broadcast)---
TIP 5: Have you checked our extensive FAQ?

   http://www.postgresql.org/docs/faq


Re: [PATCHES] avg(int2) and avg(int8) micro-opt

2005-04-04 Thread Neil Conway
Tom Lane wrote:
Why only those two?  Might as well make all the accum functions look alike.
Yeah, there might be some others we could improve. float4_accum() and 
float8_accum() look like they could be improved pretty easily, and 
do_numeric_accum() should also be fixable with some hackery. I suppose 
it's also worth optimizing int2_sum(), int4_sum() and int8_sum(). I'll 
send a patch for this later today or tomorrow. Are there any other 
transition functions where we can apply this technique?

BTW, int2_avg_accum() and int4_avg_accum() patch applied to HEAD.
-Neil
---(end of broadcast)---
TIP 9: the planner will ignore your desire to choose an index scan if your
 joining column's datatypes do not match


Re: [PATCHES] avg(int2) and avg(int8) micro-opt

2005-04-04 Thread Tom Lane
Neil Conway <[EMAIL PROTECTED]> writes:
> This patch changes int2_avg_accum() and int4_avg_accum() use the nodeAgg 
> performance hack Tom introduced recently.

Why only those two?  Might as well make all the accum functions look alike.

> It is possible that the transition array might be TOAST'ed (not that I'd 
> expect that to occur in practice, of course).

AFAICS that is impossible, since the transition value is never stored to
disk.  But your analysis is good anyway.

regards, tom lane

---(end of broadcast)---
TIP 7: don't forget to increase your free space map settings