From baf0e7b28111337c6b9f138ddea7c2ef137fd930 Mon Sep 17 00:00:00 2001 From: Jeff Davis Date: Mon, 4 May 2026 14:29:35 -0700 Subject: [PATCH v4 3/3] Update Hash Aggregation to use memory pools. This reverts commit 50a38f65177ea7858bc97f71ba0757ba04c1c167, which is no longer needed. --- src/backend/executor/execUtils.c | 69 +++++++------------------------- src/backend/executor/nodeAgg.c | 37 +++++------------ src/include/executor/executor.h | 1 - 3 files changed, 24 insertions(+), 83 deletions(-) diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 1eb6b9f1f40..4b8d1c900b3 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -234,13 +234,21 @@ FreeExecutorState(EState *estate) MemoryContextDelete(estate->es_query_cxt); } -/* - * Internal implementation for CreateExprContext() and CreateWorkExprContext() - * that allows control over the AllocSet parameters. +/* ---------------- + * CreateExprContext + * + * Create a context for expression evaluation within an EState. + * + * An executor run may require multiple ExprContexts (we usually make one + * for each Plan node, and a separate one for per-output-tuple processing + * such as constraint checking). Each ExprContext has its own "per-tuple" + * memory context. + * + * Note we make no assumption about the caller's memory context. + * ---------------- */ -static ExprContext * -CreateExprContextInternal(EState *estate, Size minContextSize, - Size initBlockSize, Size maxBlockSize) +ExprContext * +CreateExprContext(EState *estate) { ExprContext *econtext; MemoryContext oldcontext; @@ -263,9 +271,7 @@ CreateExprContextInternal(EState *estate, Size minContextSize, econtext->ecxt_per_tuple_memory = AllocSetContextCreate(estate->es_query_cxt, "ExprContext", - minContextSize, - initBlockSize, - maxBlockSize); + ALLOCSET_DEFAULT_SIZES); econtext->ecxt_param_exec_vals = estate->es_param_exec_vals; econtext->ecxt_param_list_info = estate->es_param_list_info; @@ -295,51 +301,6 @@ CreateExprContextInternal(EState *estate, Size minContextSize, return econtext; } -/* ---------------- - * CreateExprContext - * - * Create a context for expression evaluation within an EState. - * - * An executor run may require multiple ExprContexts (we usually make one - * for each Plan node, and a separate one for per-output-tuple processing - * such as constraint checking). Each ExprContext has its own "per-tuple" - * memory context. - * - * Note we make no assumption about the caller's memory context. - * ---------------- - */ -ExprContext * -CreateExprContext(EState *estate) -{ - return CreateExprContextInternal(estate, ALLOCSET_DEFAULT_SIZES); -} - - -/* ---------------- - * CreateWorkExprContext - * - * Like CreateExprContext, but specifies the AllocSet sizes to be reasonable - * in proportion to work_mem. If the maximum block allocation size is too - * large, it's easy to skip right past work_mem with a single allocation. - * ---------------- - */ -ExprContext * -CreateWorkExprContext(EState *estate) -{ - Size maxBlockSize; - - maxBlockSize = pg_prevpower2_size_t(work_mem * (Size) 1024 / 16); - - /* But no bigger than ALLOCSET_DEFAULT_MAXSIZE */ - maxBlockSize = Min(maxBlockSize, ALLOCSET_DEFAULT_MAXSIZE); - - /* and no smaller than ALLOCSET_DEFAULT_INITSIZE */ - maxBlockSize = Max(maxBlockSize, ALLOCSET_DEFAULT_INITSIZE); - - return CreateExprContextInternal(estate, ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, maxBlockSize); -} - /* ---------------- * CreateStandaloneExprContext * diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 925caadd2ce..01334d6012e 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -1866,12 +1866,9 @@ static void hash_agg_check_limits(AggState *aggstate) { uint64 ngroups = aggstate->hash_ngroups_current; - Size meta_mem = MemoryContextMemAllocated(aggstate->hash_metacxt, - true); - Size entry_mem = MemoryContextMemAllocated(aggstate->hash_tuplescxt, - true); - Size tval_mem = MemoryContextMemAllocated(aggstate->hashcontext->ecxt_per_tuple_memory, - true); + Size meta_mem = MemoryContextGetPool(aggstate->hash_metacxt)->allocated; + Size entry_mem = MemoryContextGetPool(aggstate->hash_tuplescxt)->allocated; + Size tval_mem = MemoryContextGetPool(aggstate->hashcontext->ecxt_per_tuple_memory)->allocated; Size total_mem = meta_mem + entry_mem + tval_mem; bool do_spill = false; @@ -1998,13 +1995,13 @@ hash_agg_update_metrics(AggState *aggstate, bool from_tape, int npartitions) static void hash_create_memory(AggState *aggstate) { - Size maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE; - /* * The hashcontext's per-tuple memory will be used for byref transition * values and returned by AggCheckCallContext(). */ - aggstate->hashcontext = CreateWorkExprContext(aggstate->ss.ps.state); + aggstate->hashcontext = CreateExprContext(aggstate->ss.ps.state); + MemoryContextCreatePool(aggstate->hashcontext->ecxt_per_tuple_memory, + work_mem * (Size) 1024); /* * The meta context will be used for the bucket array of @@ -2017,6 +2014,7 @@ hash_create_memory(AggState *aggstate) aggstate->hash_metacxt = AllocSetContextCreate(aggstate->ss.ps.state->es_query_cxt, "HashAgg meta context", ALLOCSET_DEFAULT_SIZES); + MemoryContextCreatePool(aggstate->hash_metacxt, work_mem * (Size) 1024); /* * The hash entries themselves, which include the grouping key @@ -2025,29 +2023,12 @@ hash_create_memory(AggState *aggstate) * entire hash table is reset. The bump allocator is faster for * allocations and avoids wasting space on the chunk header or * power-of-two allocations. - * - * Like CreateWorkExprContext(), use smaller sizings for smaller work_mem, - * to avoid large jumps in memory usage. - */ - - /* - * Like CreateWorkExprContext(), use smaller sizings for smaller work_mem, - * to avoid large jumps in memory usage. */ - maxBlockSize = pg_prevpower2_size_t(work_mem * (Size) 1024 / 16); - - /* But no bigger than ALLOCSET_DEFAULT_MAXSIZE */ - maxBlockSize = Min(maxBlockSize, ALLOCSET_DEFAULT_MAXSIZE); - - /* and no smaller than ALLOCSET_DEFAULT_INITSIZE */ - maxBlockSize = Max(maxBlockSize, ALLOCSET_DEFAULT_INITSIZE); aggstate->hash_tuplescxt = BumpContextCreate(aggstate->ss.ps.state->es_query_cxt, "HashAgg hashed tuples", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - maxBlockSize); - + ALLOCSET_DEFAULT_SIZES); + MemoryContextCreatePool(aggstate->hash_tuplescxt, work_mem * (Size) 1024); } /* diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 33bbdbfeffb..1e72fbef6f9 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -653,7 +653,6 @@ extern void end_tup_output(TupOutputState *tstate); extern EState *CreateExecutorState(void); extern void FreeExecutorState(EState *estate); extern ExprContext *CreateExprContext(EState *estate); -extern ExprContext *CreateWorkExprContext(EState *estate); extern ExprContext *CreateStandaloneExprContext(void); extern void FreeExprContext(ExprContext *econtext, bool isCommit); extern void ReScanExprContext(ExprContext *econtext); -- 2.43.0