Attached is a patch that fixes a gradual memory leak in ExecReScanAgg(),
when the AGG_HASHED strategy is used:

    * the aggregation hash table is allocated in a newly-created
      sub-context of the agg's aggcontext

    * MemoryContextReset() resets the memory allocated in child
      contexts, but not the child contexts themselves

    * ExecReScanAgg() builds a brand-new hash table, which allocates
      a brand-new sub-context, thus leaking the header for the
      previous hashtable sub-context

The patch fixes this by using MemoryContextDeleteAndResetChildren(). (I
briefly looked at other call-sites of hash_create() to see if this
problem exists elsewhere, but I didn't see anything obvious.)

We run into the leak quite easily at Truviso; with a sufficiently
long-lived query in vanilla Postgres, you should be able to reproduce
the same problem.

Credit: Sailesh Krishnamurthy at Truviso for diagnosing the cause of the
leak.

-Neil

Index: src/backend/executor/nodeAgg.c
===================================================================
RCS file: /home/neilc/postgres/cvs_root/pgsql/src/backend/executor/nodeAgg.c,v
retrieving revision 1.152
diff -p -c -r1.152 nodeAgg.c
*** src/backend/executor/nodeAgg.c	2 Apr 2007 03:49:38 -0000	1.152
--- src/backend/executor/nodeAgg.c	6 Aug 2007 19:29:11 -0000
*************** ExecReScanAgg(AggState *node, ExprContex
*** 1646,1653 ****
  	MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
  	MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
  
! 	/* Release all temp storage */
! 	MemoryContextReset(node->aggcontext);
  
  	if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
  	{
--- 1646,1657 ----
  	MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
  	MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
  
! 	/*
! 	 * Release all temp storage. Note that in the AGG_HASHED case the agg
! 	 * hash table is allocated in a sub-context, so we need to use
! 	 * MemoryContextResetAndDeleteChildren() to reclaim that storage.
! 	 */
! 	MemoryContextResetAndDeleteChildren(node->aggcontext);
  
  	if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
  	{
---------------------------(end of broadcast)---------------------------
TIP 7: You can help support the PostgreSQL project by donating at

                http://www.postgresql.org/about/donate

Reply via email to