Incorporate a couple of recent tuplesort.c improvements into tuplestore.c.

In particular, ensure that enlargement of the memtuples[] array doesn't
fall foul of MaxAllocSize when work_mem is very large, and don't bother
enlarging it if that would force an immediate switch into 'tape' mode anyway.
This commit is contained in:
Tom Lane 2006-03-04 19:30:12 +00:00
parent 20bdc71369
commit 2689abf078
1 changed files with 24 additions and 11 deletions

View File

@ -36,7 +36,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.25 2005/11/22 18:17:27 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.26 2006/03/04 19:30:12 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -316,15 +316,28 @@ tuplestore_puttuple(Tuplestorestate *state, void *tuple)
switch (state->status) switch (state->status)
{ {
case TSS_INMEM: case TSS_INMEM:
/* Grow the array as needed */ /*
if (state->memtupcount >= state->memtupsize) * Grow the array as needed. Note that we try to grow the array
* when there is still one free slot remaining --- if we fail,
* there'll still be room to store the incoming tuple, and then
* we'll switch to tape-based operation.
*/
if (state->memtupcount >= state->memtupsize - 1)
{ {
FREEMEM(state, GetMemoryChunkSpace(state->memtuples)); /*
state->memtupsize *= 2; * See grow_memtuples() in tuplesort.c for the rationale
state->memtuples = (void **) * behind these two tests.
repalloc(state->memtuples, */
state->memtupsize * sizeof(void *)); if (state->availMem > (long) (state->memtupsize * sizeof(void *)) &&
USEMEM(state, GetMemoryChunkSpace(state->memtuples)); (Size) (state->memtupsize * 2) < MaxAllocSize / sizeof(void *))
{
FREEMEM(state, GetMemoryChunkSpace(state->memtuples));
state->memtupsize *= 2;
state->memtuples = (void **)
repalloc(state->memtuples,
state->memtupsize * sizeof(void *));
USEMEM(state, GetMemoryChunkSpace(state->memtuples));
}
} }
/* Stash the tuple in the in-memory array */ /* Stash the tuple in the in-memory array */
@ -335,9 +348,9 @@ tuplestore_puttuple(Tuplestorestate *state, void *tuple)
state->current = state->memtupcount; state->current = state->memtupcount;
/* /*
* Done if we still fit in available memory. * Done if we still fit in available memory and have array slots.
*/ */
if (!LACKMEM(state)) if (state->memtupcount < state->memtupsize && !LACKMEM(state))
return; return;
/* /*