From f7d54f4f7ddf72bf4db1783890b058e758b4b894 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Thu, 8 Dec 2016 10:15:24 +0200 Subject: [PATCH] Fix accounting of memory needed for merge heap. We allegedly allocated all remaining memory for the read buffers of the sort tapes, but we allocated the merge heap only after that. That means that the allocation of the merge heap was guaranteed to go over the memory limit. Fix by allocating the merge heap first. This makes little difference in practice, because the merge heap is tiny, but let's tidy. While we're at it, add a safeguard for the case that we are already over the limit when allocating the read buffers. That shouldn't happen, but better safe than sorry. The memory accounting error was reported off-list by Peter Geoghegan. --- src/backend/utils/sort/tuplesort.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 3ad81862f3..46eecbf942 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -2637,8 +2637,16 @@ mergeruns(Tuplesortstate *state) } /* - * Use all the spare memory we have available for read buffers among the - * input tapes. + * Allocate a new 'memtuples' array, for the heap. It will hold one tuple + * from each input tape. + */ + state->memtupsize = numInputTapes; + state->memtuples = (SortTuple *) palloc(numInputTapes * sizeof(SortTuple)); + USEMEM(state, GetMemoryChunkSpace(state->memtuples)); + + /* + * Use all the remaining memory we have available for read buffers among + * the input tapes. * * We do this only after checking for the case that we produced only one * initial run, because there is no need to use a large read buffer when @@ -2661,17 +2669,9 @@ mergeruns(Tuplesortstate *state) (state->availMem) / 1024, numInputTapes); #endif - state->read_buffer_size = state->availMem / numInputTapes; + state->read_buffer_size = Min(state->availMem / numInputTapes, 0); USEMEM(state, state->availMem); - /* - * Allocate a new 'memtuples' array, for the heap. It will hold one tuple - * from each input tape. - */ - state->memtupsize = numInputTapes; - state->memtuples = (SortTuple *) palloc(numInputTapes * sizeof(SortTuple)); - USEMEM(state, GetMemoryChunkSpace(state->memtuples)); - /* End of step D2: rewind all output tapes to prepare for merging */ for (tapenum = 0; tapenum < state->tapeRange; tapenum++) LogicalTapeRewindForRead(state->tapeset, tapenum, state->read_buffer_size);