From 1cc587b776bd8922c2b2f465e50250b5727243f2 Mon Sep 17 00:00:00 2001 From: David Geier Date: Fri, 18 Sep 2026 12:17:11 +0200 Subject: [PATCH v2 2/8] Allocate RelationData structs in a dedicated slab context The power-of-two size classes of aset mean that reductions in the size of RelationData often yield no actual memory savings, as the allocation is rounded up to the next size class anyway. RelationData objects are fixed-size and numerous, so they are a good fit for a slab allocator. Create a slab context as a child of CacheMemoryContext in RelationCacheInitialize() and allocate all RelationData structs there; subsidiary allocations remain in CacheMemoryContext itself. --- src/backend/utils/cache/relcache.c | 44 +++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index dc42f2c4c1f..27eff372298 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -137,6 +137,14 @@ typedef struct relidcacheent static HTAB *RelationIdCache; +/* + * Slab memory context holding all the relcache's RelationData structs. + * It is a child of CacheMemoryContext; only the fixed-size RelationData + * objects are allocated there, while all subsidiary data stays in + * CacheMemoryContext itself. + */ +static MemoryContext RelationSlabContext = NULL; + /* * This flag is false until we have prepared the critical relcache entries * that are needed to do indexscans on the tables read by relcache building. @@ -420,13 +428,16 @@ AllocateRelationDesc(Form_pg_class relp) MemoryContext oldcxt; Form_pg_class relationForm; - /* Relcache entries must live in CacheMemoryContext */ - oldcxt = MemoryContextSwitchTo(CacheMemoryContext); - /* - * allocate and zero space for new relation descriptor + * Allocate and zero space for new relation descriptor. The RelationData + * struct goes into RelationSlabContext; all subsidiary data is allocated + * in CacheMemoryContext. */ - relation = palloc0_object(RelationData); + relation = MemoryContextAllocZero(RelationSlabContext, + sizeof(RelationData)); + + /* Relcache subsidiary data must live in CacheMemoryContext */ + oldcxt = MemoryContextSwitchTo(CacheMemoryContext); /* make sure relation is marked as having no open file yet */ relation->rd_smgr = NULL; @@ -1892,9 +1903,11 @@ formrdesc(const char *relationName, Oid relationReltype, bool has_not_null; /* - * allocate new relation desc, clear all fields of reldesc + * allocate new relation desc, clear all fields of reldesc; the + * RelationData struct itself goes into RelationSlabContext */ - relation = palloc0_object(RelationData); + relation = MemoryContextAllocZero(RelationSlabContext, + sizeof(RelationData)); /* make sure relation is marked as having no open file yet */ relation->rd_smgr = NULL; @@ -3564,9 +3577,11 @@ RelationBuildLocalRelation(const char *relname, oldcxt = MemoryContextSwitchTo(CacheMemoryContext); /* - * allocate a new relation descriptor and fill in basic state fields. + * allocate a new relation descriptor and fill in basic state fields; the + * RelationData struct itself goes into RelationSlabContext */ - rel = palloc0_object(RelationData); + rel = MemoryContextAllocZero(RelationSlabContext, + sizeof(RelationData)); /* make sure relation is marked as having no open file yet */ rel->rd_smgr = NULL; @@ -3999,6 +4014,14 @@ RelationCacheInitialize(void) if (!CacheMemoryContext) CreateCacheMemoryContext(); + /* + * create the slab context holding the relcache's RelationData structs + */ + RelationSlabContext = SlabContextCreate(CacheMemoryContext, + "RelationSlabContext", + SLAB_DEFAULT_BLOCK_SIZE, + sizeof(RelationData)); + /* * create hashtable that indexes the relcache */ @@ -6298,7 +6321,8 @@ load_relcache_init_file(bool shared) rels = repalloc_array(rels, Relation, max_rels); } - rel = rels[num_rels++] = (Relation) palloc(len); + rel = rels[num_rels++] = (Relation) + MemoryContextAlloc(RelationSlabContext, len); /* then, read the Relation structure */ if (fread(rel, 1, len, fp) != len) -- 2.55.0