diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c index 71a396d4456..654d16bc8e8 100644 --- a/src/backend/utils/mmgr/aset.c +++ b/src/backend/utils/mmgr/aset.c @@ -89,7 +89,8 @@ * * With the current parameters, request sizes up to 8K are treated as chunks, * larger requests go into dedicated blocks. Change ALLOCSET_NUM_FREELISTS - * to adjust the boundary point. + * to adjust the boundary point; and adjust ALLOCSET_SEPARATE_THRESHOLD in + * memutils.h to agree. *-------------------- */ @@ -385,7 +386,11 @@ AllocSetContextCreate(MemoryContext parent, * allocChunkLimit a power of two, because the requested and * actually-allocated sizes of any chunk must be on the same side of the * limit, else we get confused about whether the chunk is "big". + * + * Also, allocChunkLimit must not exceed ALLOCSET_SEPARATE_THRESHOLD. */ + Assert(ALLOC_CHUNK_LIMIT == ALLOCSET_SEPARATE_THRESHOLD); + context->allocChunkLimit = ALLOC_CHUNK_LIMIT; while (context->allocChunkLimit > (Size) (maxBlockSize - ALLOC_BLOCKHDRSZ - ALLOC_CHUNKHDRSZ)) diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 4900796e405..24591e3dc8a 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -531,7 +531,14 @@ tuplesort_begin_common(int workMem, bool randomAccess) state->tapeset = NULL; state->memtupcount = 0; - state->memtupsize = 1024; /* initial guess */ + + /* + * Initial size of array must be more than ALLOCSET_SEPARATE_THRESHOLD; + * see comments in grow_memtuples(). + */ + state->memtupsize = Max(1024, + ALLOCSET_SEPARATE_THRESHOLD / sizeof(SortTuple) + 1); + state->memtuples = (SortTuple *) palloc(state->memtupsize * sizeof(SortTuple)); USEMEM(state, GetMemoryChunkSpace(state->memtuples)); @@ -897,7 +904,7 @@ grow_memtuples(Tuplesortstate *state) state->memtupsize * sizeof(SortTuple)); USEMEM(state, GetMemoryChunkSpace(state->memtuples)); if (LACKMEM(state)) - elog(ERROR, "unexpected out-of-memory situation during sort"); + elog(ERROR, "unexpected out-of-memory situation in tuplesort"); return true; } diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c index 55c8eca7957..4dfc5f6c5f3 100644 --- a/src/backend/utils/sort/tuplestore.c +++ b/src/backend/utils/sort/tuplestore.c @@ -261,7 +261,14 @@ tuplestore_begin_common(int eflags, bool interXact, int maxKBytes) state->memtupdeleted = 0; state->memtupcount = 0; - state->memtupsize = 1024; /* initial guess */ + + /* + * Initial size of array must be more than ALLOCSET_SEPARATE_THRESHOLD; + * see comments in grow_memtuples(). + */ + state->memtupsize = Max(16384 / sizeof(void *), + ALLOCSET_SEPARATE_THRESHOLD / sizeof(void *) + 1); + state->memtuples = (void **) palloc(state->memtupsize * sizeof(void *)); USEMEM(state, GetMemoryChunkSpace(state->memtuples)); @@ -644,6 +651,8 @@ tuplestore_puttuple_common(Tuplestorestate *state, void *tuple) repalloc(state->memtuples, state->memtupsize * sizeof(void *)); USEMEM(state, GetMemoryChunkSpace(state->memtuples)); + if (LACKMEM(state)) + elog(ERROR, "unexpected out-of-memory situation in tuplestore"); } } diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h index d4a9d46dae7..c76d1aad2f4 100644 --- a/src/include/utils/memutils.h +++ b/src/include/utils/memutils.h @@ -136,4 +136,12 @@ extern MemoryContext AllocSetContextCreate(MemoryContext parent, #define ALLOCSET_SMALL_INITSIZE (1 * 1024) #define ALLOCSET_SMALL_MAXSIZE (8 * 1024) +/* + * Threshold above which a request in an AllocSet context is certain to be + * allocated separately (and thereby have constant allocation overhead). + * Few callers should be interested in this, but tuplesort/tuplestore need + * to know it. + */ +#define ALLOCSET_SEPARATE_THRESHOLD 8192 + #endif /* MEMUTILS_H */