v0-0001-Add-bitspace-for-more-memory-context-types-in-Mem.patch.txt

text/plain

Filename: v0-0001-Add-bitspace-for-more-memory-context-types-in-Mem.patch.txt
Type: text/plain
Part: 0
Message: Re: Add bump memory context type and use it for tuplesorts
From 4c0b4b1af98fcfecf80a30ea1834668b59d543a5 Mon Sep 17 00:00:00 2001
From: Matthias van de Meent <boekewurm+postgres@gmail.com>
Date: Thu, 4 Apr 2024 21:34:46 +0200
Subject: [PATCH v0] Add bitspace for more memory context types in
 MemoryChunk's hdrmask

Assuming we don't want to use patterns from unused memory, common
glibc malloc patterns, and wipe_mem-ed memory, we now have 18 new IDs
to work with again, from 0.

In passing, simplify/clean up initialization of unused memory contexts
in the mcxt_methods array.

Inspiration: https://postgr.es/m/CAApHDvqGSpCU95TmM%3DBp%3D6xjL_nLys4zdZOpfNyWBk97Xrdj2w%40mail.gmail.com
---
 src/backend/utils/mmgr/mcxt.c            | 55 +++++++++++++++---------
 src/include/utils/memutils_internal.h    | 35 ++++++++++++---
 src/include/utils/memutils_memorychunk.h | 15 ++++---
 3 files changed, 73 insertions(+), 32 deletions(-)

diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index 5d426795d9..9373f782ce 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -102,26 +102,41 @@ static const MemoryContextMethods mcxt_methods[] = {
 	 * seems sufficient to provide routines for the methods that might get
 	 * invoked from inspection of a chunk (see MCXT_METHOD calls below).
 	 */
-
-	[MCTX_UNUSED1_ID].free_p = BogusFree,
-	[MCTX_UNUSED1_ID].realloc = BogusRealloc,
-	[MCTX_UNUSED1_ID].get_chunk_context = BogusGetChunkContext,
-	[MCTX_UNUSED1_ID].get_chunk_space = BogusGetChunkSpace,
-
-	[MCTX_UNUSED2_ID].free_p = BogusFree,
-	[MCTX_UNUSED2_ID].realloc = BogusRealloc,
-	[MCTX_UNUSED2_ID].get_chunk_context = BogusGetChunkContext,
-	[MCTX_UNUSED2_ID].get_chunk_space = BogusGetChunkSpace,
-
-	[MCTX_UNUSED3_ID].free_p = BogusFree,
-	[MCTX_UNUSED3_ID].realloc = BogusRealloc,
-	[MCTX_UNUSED3_ID].get_chunk_context = BogusGetChunkContext,
-	[MCTX_UNUSED3_ID].get_chunk_space = BogusGetChunkSpace,
-
-	[MCTX_UNUSED4_ID].free_p = BogusFree,
-	[MCTX_UNUSED4_ID].realloc = BogusRealloc,
-	[MCTX_UNUSED4_ID].get_chunk_context = BogusGetChunkContext,
-	[MCTX_UNUSED4_ID].get_chunk_space = BogusGetChunkSpace,
+#define BOGUS_MCTX(id) \
+	[id].free_p = BogusFree, \
+	[id].realloc = BogusRealloc, \
+	[id].get_chunk_context = BogusGetChunkContext, \
+	[id].get_chunk_space = BogusGetChunkSpace
+
+	BOGUS_MCTX(MCTX_UNUSED1_ID),
+	BOGUS_MCTX(MCTX_UNUSED2_ID),
+	BOGUS_MCTX(MCTX_UNUSED3_ID),
+	BOGUS_MCTX(MCTX_UNUSED4_ID),
+	BOGUS_MCTX(MCTX_UNUSED5_ID),
+	BOGUS_MCTX(MCTX_UNUSED6_ID),
+	BOGUS_MCTX(MCTX_UNUSED7_ID),
+	BOGUS_MCTX(MCTX_UNUSED8_ID),
+	BOGUS_MCTX(MCTX_UNUSED9_ID),
+	BOGUS_MCTX(MCTX_UNUSED10_ID),
+	BOGUS_MCTX(MCTX_UNUSED11_ID),
+	BOGUS_MCTX(MCTX_UNUSED12_ID),
+	BOGUS_MCTX(MCTX_UNUSED13_ID),
+	BOGUS_MCTX(MCTX_UNUSED14_ID),
+	BOGUS_MCTX(MCTX_UNUSED15_ID),
+	BOGUS_MCTX(MCTX_UNUSED16_ID),
+	BOGUS_MCTX(MCTX_UNUSED17_ID),
+	BOGUS_MCTX(MCTX_UNUSED18_ID),
+	BOGUS_MCTX(MCTX_UNUSED19_ID),
+	BOGUS_MCTX(MCTX_UNUSED20_ID),
+	BOGUS_MCTX(MCTX_UNUSED21_ID),
+	BOGUS_MCTX(MCTX_UNUSED22_ID),
+	BOGUS_MCTX(MCTX_UNUSED23_ID),
+	BOGUS_MCTX(MCTX_UNUSED24_ID),
+	BOGUS_MCTX(MCTX_UNUSED25_ID),
+	BOGUS_MCTX(MCTX_UNUSED26_ID),
+	BOGUS_MCTX(MCTX_UNUSED27_ID),
+	BOGUS_MCTX(MCTX_UNUSED28_ID)
+#undef BOGUS_MCTX
 };
 
 /*
diff --git a/src/include/utils/memutils_internal.h b/src/include/utils/memutils_internal.h
index ad1048fd82..fbf5ecd111 100644
--- a/src/include/utils/memutils_internal.h
+++ b/src/include/utils/memutils_internal.h
@@ -104,21 +104,46 @@ extern Size AlignedAllocGetChunkSpace(void *pointer);
  */
 typedef enum MemoryContextMethodID
 {
-	MCTX_UNUSED1_ID,			/* 000 occurs in never-used memory */
-	MCTX_UNUSED2_ID,			/* glibc malloc'd chunks usually match 001 */
-	MCTX_UNUSED3_ID,			/* glibc malloc'd chunks > 128kB match 010 */
+	MCTX_UNUSED1_ID,			/* 00000 occurs in never-used memory */
+	MCTX_UNUSED2_ID,			/* glibc malloc'd chunks usually match XX001 */
+	MCTX_UNUSED3_ID,			/* glibc malloc'd chunks > 128kB match XX010 */
 	MCTX_ASET_ID,
 	MCTX_GENERATION_ID,
 	MCTX_SLAB_ID,
 	MCTX_ALIGNED_REDIRECT_ID,
-	MCTX_UNUSED4_ID,			/* 111 occurs in wipe_mem'd memory */
+	MCTX_UNUSED4_ID,			/* 00111 */
+	MCTX_UNUSED5_ID,			/* 01000 */
+	MCTX_UNUSED6_ID,			/* glibc malloc'd chunks usually match XX001 */
+	MCTX_UNUSED7_ID,			/* glibc malloc'd chunks > 128kB match XX010 */
+	MCTX_UNUSED8_ID,			/* 01011 */
+	MCTX_UNUSED9_ID,			/* 01100 */
+	MCTX_UNUSED10_ID,			/* 01101 */
+	MCTX_UNUSED11_ID,			/* 01110 */
+	MCTX_UNUSED12_ID,			/* 01111 */
+	MCTX_UNUSED13_ID,			/* 10000 */
+	MCTX_UNUSED14_ID,			/* glibc malloc'd chunks usually match XX001 */
+	MCTX_UNUSED15_ID,			/* glibc malloc'd chunks > 128kB match XX010 */
+	MCTX_UNUSED16_ID,			/* 10011 */
+	MCTX_UNUSED17_ID,			/* 10100 */
+	MCTX_UNUSED18_ID,			/* 10101 */
+	MCTX_UNUSED19_ID,			/* 10110 */
+	MCTX_UNUSED20_ID,			/* 10111 */
+	MCTX_UNUSED21_ID,			/* 11000 */
+	MCTX_UNUSED22_ID,			/* glibc malloc'd chunks usually match XX001 */
+	MCTX_UNUSED23_ID,			/* glibc malloc'd chunks > 128kB match XX010 */
+	MCTX_UNUSED24_ID,			/* 11011 */
+	MCTX_UNUSED25_ID,			/* 11100 */
+	MCTX_UNUSED26_ID,			/* 11101 */
+	MCTX_UNUSED27_ID,			/* 11110 */
+	MCTX_UNUSED28_ID			/* 11111 occurs in wipe_mem'd memory (0x7F) */
+#define MaxMemoryContextMethodID (MCTX_UNUSED28_ID)
 } MemoryContextMethodID;
 
 /*
  * The number of bits that 8-byte memory chunk headers can use to encode the
  * MemoryContextMethodID.
  */
-#define MEMORY_CONTEXT_METHODID_BITS 3
+#define MEMORY_CONTEXT_METHODID_BITS 5
 #define MEMORY_CONTEXT_METHODID_MASK \
 	((((uint64) 1) << MEMORY_CONTEXT_METHODID_BITS) - 1)
 
diff --git a/src/include/utils/memutils_memorychunk.h b/src/include/utils/memutils_memorychunk.h
index 38296abe1b..86ed28afab 100644
--- a/src/include/utils/memutils_memorychunk.h
+++ b/src/include/utils/memutils_memorychunk.h
@@ -25,14 +25,14 @@
  * used to encode 4 separate pieces of information.  Starting with the least
  * significant bits of 'hdrmask', the bit space is reserved as follows:
  *
- * 1.	3-bits to indicate the MemoryContextMethodID as defined by
+ * 1.	5-bits to indicate the MemoryContextMethodID as defined by
  *		MEMORY_CONTEXT_METHODID_MASK
  * 2.	1-bit to denote an "external" chunk (see below)
  * 3.	30-bits reserved for the MemoryContext to use for anything it
  *		requires.  Most MemoryContext likely want to store the size of the
  *		chunk here.
- * 4.	30-bits for the number of bytes that must be subtracted from the chunk
- *		to obtain the address of the block that the chunk is stored on.
+ * 4.	28-bits for the multiple of 4 bytes that must be subtracted from the
+ *		chunk to obtain the address of the block that the chunk is stored on.
  *
  * In some cases, for example when memory allocations become large, it's
  * possible fields 3 and 4 above are not large enough to store the values
@@ -91,7 +91,7 @@
  * The maximum distance in bytes that a MemoryChunk can be offset from the
  * block that is storing the chunk.  Must be 1 less than a power of 2.
  */
-#define MEMORYCHUNK_MAX_BLOCKOFFSET		UINT64CONST(0x3FFFFFFF)
+#define MEMORYCHUNK_MAX_BLOCKOFFSET		UINT64CONST(0xFFFFFFF)
 
 /* define the least significant base-0 bit of each portion of the hdrmask */
 #define MEMORYCHUNK_EXTERNAL_BASEBIT	MEMORY_CONTEXT_METHODID_BITS
@@ -135,7 +135,7 @@ typedef struct MemoryChunk
  * optimize out the & MEMORYCHUNK_MAX_BLOCKOFFSET.
  */
 #define HdrMaskBlockOffset(hdrmask) \
-	(((hdrmask) >> MEMORYCHUNK_BLOCKOFFSET_BASEBIT) & MEMORYCHUNK_MAX_BLOCKOFFSET)
+	((((hdrmask) >> MEMORYCHUNK_BLOCKOFFSET_BASEBIT) & MEMORYCHUNK_MAX_BLOCKOFFSET) * 4)
 
 /* For external chunks only, check the magic number matches */
 #define HdrMaskCheckMagic(hdrmask) \
@@ -157,11 +157,12 @@ MemoryChunkSetHdrMask(MemoryChunk *chunk, void *block,
 	Size		blockoffset = (char *) chunk - (char *) block;
 
 	Assert((char *) chunk >= (char *) block);
-	Assert(blockoffset <= MEMORYCHUNK_MAX_BLOCKOFFSET);
+	Assert((blockoffset % 4) == 0);
+	Assert((blockoffset / 4) <= MEMORYCHUNK_MAX_BLOCKOFFSET);
 	Assert(value <= MEMORYCHUNK_MAX_VALUE);
 	Assert((int) methodid <= MEMORY_CONTEXT_METHODID_MASK);
 
-	chunk->hdrmask = (((uint64) blockoffset) << MEMORYCHUNK_BLOCKOFFSET_BASEBIT) |
+	chunk->hdrmask = (((uint64) (blockoffset / 4)) << MEMORYCHUNK_BLOCKOFFSET_BASEBIT) |
 		(((uint64) value) << MEMORYCHUNK_VALUE_BASEBIT) |
 		methodid;
 }
-- 
2.40.1