diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
new file mode 100644
index 1452e8c..9c5d85a
*** a/src/backend/utils/sort/tuplesort.c
--- b/src/backend/utils/sort/tuplesort.c
*************** struct Tuplesortstate
*** 273,278 ****
--- 273,280 ----
  	SortTuple  *memtuples;		/* array of SortTuple structs */
  	int			memtupcount;	/* number of tuples currently present */
  	int			memtupsize;		/* allocated length of memtuples array */
+ 	bool			final_memtupsize;	/* true if we are no longer growing memtupsize */
+ 
  
  	/*
  	 * While building initial runs, this is the current output run number
*************** tuplesort_begin_common(int workMem, bool
*** 546,551 ****
--- 548,554 ----
  	state->randomAccess = randomAccess;
  	state->bounded = false;
  	state->boundUsed = false;
+ 	state->final_memtupsize = false;
  	state->allowedMem = workMem * 1024L;
  	state->availMem = state->allowedMem;
  	state->sortcontext = sortcontext;
*************** tuplesort_end(Tuplesortstate *state)
*** 937,950 ****
   * Grow the memtuples[] array, if possible within our memory constraint.
   * Return TRUE if able to enlarge the array, FALSE if not.
   *
!  * At each increment we double the size of the array.  When we are short
   * on memory we could consider smaller increases, but because availMem
!  * moves around with tuple addition/removal, this might result in thrashing.
   * Small increases in the array size are likely to be pretty inefficient.
   */
  static bool
  grow_memtuples(Tuplesortstate *state)
  {
  	/*
  	 * We need to be sure that we do not cause LACKMEM to become true, else
  	 * the space management algorithm will go nuts.  We assume here that the
--- 940,957 ----
   * Grow the memtuples[] array, if possible within our memory constraint.
   * Return TRUE if able to enlarge the array, FALSE if not.
   *
!  * At each increment except possibly the last one we double the size of
!  * the array.  When we are short
   * on memory we could consider smaller increases, but because availMem
!  * moves around with tuple addition/removal, this might result in thrashing,
!  * so only allow it to happen once.
   * Small increases in the array size are likely to be pretty inefficient.
   */
  static bool
  grow_memtuples(Tuplesortstate *state)
  {
+ 	int new_memtupsize;
+ 
  	/*
  	 * We need to be sure that we do not cause LACKMEM to become true, else
  	 * the space management algorithm will go nuts.  We assume here that the
*************** grow_memtuples(Tuplesortstate *state)
*** 953,971 ****
  	 * minimum array size established in tuplesort_begin_common is large
  	 * enough to force palloc to treat it as a separate chunk, so this
  	 * assumption should be good.  But let's check it.)
  	 */
! 	if (state->availMem <= (long) (state->memtupsize * sizeof(SortTuple)))
  		return false;
  
  	/*
  	 * On a 64-bit machine, allowedMem could be high enough to get us into
  	 * trouble with MaxAllocSize, too.
  	 */
! 	if ((Size) (state->memtupsize * 2) >= MaxAllocSize / sizeof(SortTuple))
  		return false;
  
  	FREEMEM(state, GetMemoryChunkSpace(state->memtuples));
! 	state->memtupsize *= 2;
  	state->memtuples = (SortTuple *)
  		repalloc(state->memtuples,
  				 state->memtupsize * sizeof(SortTuple));
--- 960,994 ----
  	 * minimum array size established in tuplesort_begin_common is large
  	 * enough to force palloc to treat it as a separate chunk, so this
  	 * assumption should be good.  But let's check it.)
+ 	 * XXXX is the new method still follow this?  The last allocation is no 
+ 	 * longer necessarily a power of 2, but that is not freed.
+ 	 *
+ 	 * Once we are approaching the final growth of memtuples, use the 
+ 	 * historical size of the tuples seen so far try to estimate the
+ 	 * best final growth size to make most efficient use of memory.
  	 */
! 	if (state->final_memtupsize)
  		return false;
+ 	if (state->availMem < state->allowedMem/2)
+ 	{
+ 		new_memtupsize = (int) ((float)state->memtupsize * (float) state->allowedMem / (float) (state->allowedMem - state->availMem));
+ 		state->final_memtupsize = true;
+ 	} 
+ 	else
+ 	{
+ 		new_memtupsize = state->memtupsize * 2;
+ 	};
+ 
  
  	/*
  	 * On a 64-bit machine, allowedMem could be high enough to get us into
  	 * trouble with MaxAllocSize, too.
  	 */
! 	if ((Size) (new_memtupsize) >= MaxAllocSize / sizeof(SortTuple))
  		return false;
  
  	FREEMEM(state, GetMemoryChunkSpace(state->memtuples));
! 	state->memtupsize = new_memtupsize;
  	state->memtuples = (SortTuple *)
  		repalloc(state->memtuples,
  				 state->memtupsize * sizeof(SortTuple));
