0003-Separate-memory-context-for-planner-s-memor-20230824.patch

text/x-patch

Filename: 0003-Separate-memory-context-for-planner-s-memor-20230824.patch
Type: text/x-patch
Part: 3
Message: Re: Report planning memory in EXPLAIN ANALYZE

Patch

Format: format-patch
Series: patch 0003
Subject: Separate memory context for planner's memory measurement
File+
src/backend/commands/explain.c 17 2
src/backend/commands/prepare.c 17 2
From 173e1df3f7a89d8c126086eacf2aa4ad87e13ac1 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
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 b014d6be7f..e7df8e4455 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