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.
This commit is contained in:
Heikki Linnakangas 2016-12-08 10:15:24 +02:00
parent cd5d3af44e
commit f7d54f4f7d
1 changed files with 11 additions and 11 deletions

View File

@ -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);