Re: avg(int2) and avg(int8) micro-opt

Поиск
Список
Период
Сортировка
От Neil Conway
Тема Re: avg(int2) and avg(int8) micro-opt
Дата
Msg-id 42539D3C.2000809@samurai.com
обсуждение исходный текст
Ответ на Re: avg(int2) and avg(int8) micro-opt  (Neil Conway <neilc@samurai.com>)
Ответы Re: avg(int2) and avg(int8) micro-opt  (Neil Conway <neilc@samurai.com>)
Список pgsql-patches
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 -0000    1.113
--- src/backend/utils/adt/float.c    6 Apr 2005 07:24:38 -0000
***************
*** 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 -0000    1.82
--- src/backend/utils/adt/numeric.c    6 Apr 2005 08:07:37 -0000
***************
*** 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_GETARG_INT16(1);

!     PG_RETURN_INT64(newval);
  }

  Datum
  int4_sum(PG_FUNCTION_ARGS)
  {
-     int64        oldsum;
      int64        newval;

      if (PG_ARGISNULL(0))
--- 2369,2407 ----
          PG_RETURN_INT64(newval);
      }

!     /*
!      * If we're invoked by nodeAgg, we can cheat and modify out first
!      * parameter in-place to avoid palloc overhead. If not, we need to
!      * return the new value of the transition variable.
!      */
!     if (fcinfo->context && IsA(fcinfo->context, AggState))
!     {
!         int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);

!         /* Leave the running sum unchanged in the new input is null */
!         if (!PG_ARGISNULL(1))
!             *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);

!         PG_RETURN_POINTER(oldsum);
!     }
!     else
!     {
!         int64        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_GETARG_INT16(1);

!         PG_RETURN_INT64(newval);
!     }
  }

  Datum
  int4_sum(PG_FUNCTION_ARGS)
  {
      int64        newval;

      if (PG_ARGISNULL(0))
***************
*** 2398,2413 ****
          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_GETARG_INT32(1);

!     PG_RETURN_INT64(newval);
  }

  Datum
--- 2414,2447 ----
          PG_RETURN_INT64(newval);
      }

!     /*
!      * If we're invoked by nodeAgg, we can cheat and modify out first
!      * parameter in-place to avoid palloc overhead. If not, we need to
!      * return the new value of the transition variable.
!      */
!     if (fcinfo->context && IsA(fcinfo->context, AggState))
!     {
!         int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);

!         /* Leave the running sum unchanged in the new input is null */
!         if (!PG_ARGISNULL(1))
!             *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);

!         PG_RETURN_POINTER(oldsum);
!     }
!     else
!     {
!         int64        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_GETARG_INT32(1);
!
!         PG_RETURN_INT64(newval);
!     }
  }

  Datum
***************
*** 2426,2431 ****
--- 2460,2471 ----
          PG_RETURN_DATUM(newval);
      }

+     /*
+      * Note that we cannot special-case the nodeAgg case here, as we
+      * do for int2_sum and int4_sum: numeric is of variable size, so
+      * we cannot modify our first parameter in-place.
+      */
+
      oldsum = PG_GETARG_NUMERIC(0);

      /* Leave sum unchanged if new input is null. */

В списке pgsql-patches по дате отправления:

Предыдущее
От: Neil Conway
Дата:
Сообщение: Re: DELETE ... USING
Следующее
От: Euler Taveira de Oliveira
Дата:
Сообщение: Re: DELETE ... USING