From eb1e4ceca14572c7f2f3bf7500d83a21b872846e Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat Date: Wed, 23 Aug 2023 11:45:47 +0530 Subject: [PATCH 3/3] Separate memory context for planner's memory measurement EXPLAIN reports memory used and allocated in current memory context by the planner. The allocated memory may be influenced by the previous activity in the current memory context. Hence use a new memory context for planning the query and report statistics from that context. Ashutosh Bapat, per suggestion from David Rowley --- src/backend/commands/explain.c | 19 +++++++++++++++++-- src/backend/commands/prepare.c | 19 +++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index efc4887244..9cd9b577c7 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -402,10 +402,24 @@ ExplainOneQuery(Query *query, int cursorOptions, MemoryContextCounters mem_counts_start; MemoryContextCounters mem_counts_end; MemUsage mem_usage; + MemoryContext planner_ctx; + MemoryContext saved_ctx; + + /* + * Create a new memory context to accurately measure memory malloc'ed + * by the planner. For further accuracy we should use the same type of + * memory context as the planner would use. That's usually AllocSet + * but ensure that. + */ + Assert(IsA(CurrentMemoryContext, AllocSetContext)); + planner_ctx = AllocSetContextCreate(CurrentMemoryContext, + "explain analyze planner context", + ALLOCSET_DEFAULT_SIZES); if (es->buffers) bufusage_start = pgBufferUsage; - MemoryContextMemConsumed(CurrentMemoryContext, &mem_counts_start); + MemoryContextMemConsumed(planner_ctx, &mem_counts_start); + saved_ctx = MemoryContextSwitchTo(planner_ctx); INSTR_TIME_SET_CURRENT(planstart); /* plan the query */ @@ -413,7 +427,8 @@ ExplainOneQuery(Query *query, int cursorOptions, INSTR_TIME_SET_CURRENT(planduration); INSTR_TIME_SUBTRACT(planduration, planstart); - MemoryContextMemConsumed(CurrentMemoryContext, &mem_counts_end); + MemoryContextSwitchTo(saved_ctx); + MemoryContextMemConsumed(planner_ctx, &mem_counts_end); calc_mem_usage(&mem_usage, &mem_counts_end, &mem_counts_start); /* calc differences of buffer counters. */ diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c index ebc0d47ba9..eb39823d7a 100644 --- a/src/backend/commands/prepare.c +++ b/src/backend/commands/prepare.c @@ -586,10 +586,24 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, MemoryContextCounters mem_counts_start; MemoryContextCounters mem_counts_end; MemUsage mem_usage; + MemoryContext planner_ctx; + MemoryContext saved_ctx; + + /* + * Create a new memory context to accurately measure memory malloc'ed by + * the planner. For further accuracy we should use the same type of memory + * context as the planner would use. That's usually AllocSet but ensure + * that. + */ + Assert(IsA(CurrentMemoryContext, AllocSetContext)); + planner_ctx = AllocSetContextCreate(CurrentMemoryContext, + "explain analyze planner context", + ALLOCSET_DEFAULT_SIZES); if (es->buffers) bufusage_start = pgBufferUsage; - MemoryContextMemConsumed(CurrentMemoryContext, &mem_counts_start); + MemoryContextMemConsumed(planner_ctx, &mem_counts_start); + saved_ctx = MemoryContextSwitchTo(planner_ctx); INSTR_TIME_SET_CURRENT(planstart); /* Look it up in the hash table */ @@ -627,7 +641,8 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, INSTR_TIME_SET_CURRENT(planduration); INSTR_TIME_SUBTRACT(planduration, planstart); - MemoryContextMemConsumed(CurrentMemoryContext, &mem_counts_end); + MemoryContextSwitchTo(saved_ctx); + MemoryContextMemConsumed(planner_ctx, &mem_counts_end); calc_mem_usage(&mem_usage, &mem_counts_end, &mem_counts_start); /* calc differences of buffer counters. */ -- 2.25.1