diff options
author | Tomas Vondra <tomas.vondra@postgresql.org> | 2025-04-02 17:08:34 +0200 |
---|---|---|
committer | Tomas Vondra <tomas.vondra@postgresql.org> | 2025-04-02 17:14:28 +0200 |
commit | 46df9487d973d00c83a7962935063f3a6518939c (patch) | |
tree | 4f2b95a76e597a3b1d1a30d240e805d4846fa0b2 /src | |
parent | f5930f9a98ea65d659d41600a138e608988ad122 (diff) | |
download | postgresql-46df9487d973d00c83a7962935063f3a6518939c.tar.gz postgresql-46df9487d973d00c83a7962935063f3a6518939c.zip |
Improve accounting for PredXactList, RWConflictPool and PGPROC
Various places allocated shared memory by first allocating a small chunk
using ShmemInitStruct(), followed by ShmemAlloc() calls to allocate more
memory. Unfortunately, ShmemAlloc() does not update ShmemIndex, so this
affected pg_shmem_allocations - it only shown the initial chunk.
This commit modifies the following allocations, to allocate everything
as a single chunk, and then split it internally.
- PredXactList
- RWConflictPool
- PGPROC structures
- Fast-Path Lock Array
The fast-path lock array is allocated separately, not as a part of the
PGPROC structures allocation.
Author: Rahila Syed <rahilasyed90@gmail.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com>
Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/CAH2L28vHzRankszhqz7deXURxKncxfirnuW68zD7+hVAqaS5GQ@mail.gmail.com
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/storage/lmgr/predicate.c | 30 | ||||
-rw-r--r-- | src/backend/storage/lmgr/proc.c | 93 |
2 files changed, 91 insertions, 32 deletions
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index 5b21a053981..d82114ffca1 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1226,14 +1226,21 @@ PredicateLockShmemInit(void) */ max_table_size *= 10; + requestSize = add_size(PredXactListDataSize, + (mul_size((Size) max_table_size, + sizeof(SERIALIZABLEXACT)))); + PredXact = ShmemInitStruct("PredXactList", - PredXactListDataSize, + requestSize, &found); Assert(found == IsUnderPostmaster); if (!found) { int i; + /* clean everything, both the header and the element */ + memset(PredXact, 0, requestSize); + dlist_init(&PredXact->availableList); dlist_init(&PredXact->activeList); PredXact->SxactGlobalXmin = InvalidTransactionId; @@ -1242,11 +1249,9 @@ PredicateLockShmemInit(void) PredXact->LastSxactCommitSeqNo = FirstNormalSerCommitSeqNo - 1; PredXact->CanPartialClearThrough = 0; PredXact->HavePartialClearedThrough = 0; - requestSize = mul_size((Size) max_table_size, - sizeof(SERIALIZABLEXACT)); - PredXact->element = ShmemAlloc(requestSize); + PredXact->element + = (SERIALIZABLEXACT *) ((char *) PredXact + PredXactListDataSize); /* Add all elements to available list, clean. */ - memset(PredXact->element, 0, requestSize); for (i = 0; i < max_table_size; i++) { LWLockInitialize(&PredXact->element[i].perXactPredicateListLock, @@ -1300,20 +1305,25 @@ PredicateLockShmemInit(void) */ max_table_size *= 5; + requestSize = RWConflictPoolHeaderDataSize + + mul_size((Size) max_table_size, + RWConflictDataSize); + RWConflictPool = ShmemInitStruct("RWConflictPool", - RWConflictPoolHeaderDataSize, + requestSize, &found); Assert(found == IsUnderPostmaster); if (!found) { int i; + /* clean everything, including the elements */ + memset(RWConflictPool, 0, requestSize); + dlist_init(&RWConflictPool->availableList); - requestSize = mul_size((Size) max_table_size, - RWConflictDataSize); - RWConflictPool->element = ShmemAlloc(requestSize); + RWConflictPool->element = (RWConflict) ((char *) RWConflictPool + + RWConflictPoolHeaderDataSize); /* Add all elements to available list, clean. */ - memset(RWConflictPool->element, 0, requestSize); for (i = 0; i < max_table_size; i++) { dlist_push_tail(&RWConflictPool->availableList, diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 066319afe2b..e9ef0fbfe32 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -91,26 +91,35 @@ static void CheckDeadLock(void); /* - * Report shared-memory space needed by InitProcGlobal. + * Report shared-memory space needed by PGPROC. */ -Size -ProcGlobalShmemSize(void) +static Size +PGProcShmemSize(void) { Size size = 0; Size TotalProcs = add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); - Size fpLockBitsSize, - fpRelIdSize; - /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + return size; +} + +/* + * Report shared-memory space needed by Fast-Path locks. + */ +static Size +FastPathLockShmemSize(void) +{ + Size size = 0; + Size TotalProcs = + add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); + Size fpLockBitsSize, + fpRelIdSize; + /* * Memory needed for PGPROC fast-path lock arrays. Make sure the sizes are * nicely aligned in each backend. @@ -124,6 +133,24 @@ ProcGlobalShmemSize(void) } /* + * Report shared-memory space needed by InitProcGlobal. + */ +Size +ProcGlobalShmemSize(void) +{ + Size size = 0; + + /* ProcGlobal */ + size = add_size(size, sizeof(PROC_HDR)); + size = add_size(size, sizeof(slock_t)); + + size = add_size(size, PGProcShmemSize()); + size = add_size(size, FastPathLockShmemSize()); + + return size; +} + +/* * Report number of semaphores needed by InitProcGlobal. */ int @@ -175,6 +202,8 @@ InitProcGlobal(void) *fpEndPtr PG_USED_FOR_ASSERTS_ONLY; Size fpLockBitsSize, fpRelIdSize; + Size requestSize; + char *ptr; /* Create the ProcGlobal shared structure */ ProcGlobal = (PROC_HDR *) @@ -204,8 +233,17 @@ InitProcGlobal(void) * with a single freelist.) Each PGPROC structure is dedicated to exactly * one of these purposes, and they do not move between groups. */ - procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC)); - MemSet(procs, 0, TotalProcs * sizeof(PGPROC)); + requestSize = PGProcShmemSize(); + + ptr = ShmemInitStruct("PGPROC structures", + requestSize, + &found); + + MemSet(ptr, 0, requestSize); + + procs = (PGPROC *) ptr; + ptr = (char *) ptr + TotalProcs * sizeof(PGPROC); + ProcGlobal->allProcs = procs; /* XXX allProcCount isn't really all of them; it excludes prepared xacts */ ProcGlobal->allProcCount = MaxBackends + NUM_AUXILIARY_PROCS; @@ -217,13 +255,17 @@ InitProcGlobal(void) * XXX: It might make sense to increase padding for these arrays, given * how hotly they are accessed. */ - ProcGlobal->xids = - (TransactionId *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->xids)); - MemSet(ProcGlobal->xids, 0, TotalProcs * sizeof(*ProcGlobal->xids)); - ProcGlobal->subxidStates = (XidCacheStatus *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->subxidStates)); - MemSet(ProcGlobal->subxidStates, 0, TotalProcs * sizeof(*ProcGlobal->subxidStates)); - ProcGlobal->statusFlags = (uint8 *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->statusFlags)); - MemSet(ProcGlobal->statusFlags, 0, TotalProcs * sizeof(*ProcGlobal->statusFlags)); + ProcGlobal->xids = (TransactionId *) ptr; + ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->xids)); + + ProcGlobal->subxidStates = (XidCacheStatus *) ptr; + ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->subxidStates)); + + ProcGlobal->statusFlags = (uint8 *) ptr; + ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->statusFlags)); + + /* make sure wer didn't overflow */ + Assert((ptr > (char *) procs) && (ptr <= (char *) procs + requestSize)); /* * Allocate arrays for fast-path locks. Those are variable-length, so @@ -233,11 +275,16 @@ InitProcGlobal(void) fpLockBitsSize = MAXALIGN(FastPathLockGroupsPerBackend * sizeof(uint64)); fpRelIdSize = MAXALIGN(FastPathLockSlotsPerBackend() * sizeof(Oid)); - fpPtr = ShmemAlloc(TotalProcs * (fpLockBitsSize + fpRelIdSize)); - MemSet(fpPtr, 0, TotalProcs * (fpLockBitsSize + fpRelIdSize)); + requestSize = FastPathLockShmemSize(); + + fpPtr = ShmemInitStruct("Fast-Path Lock Array", + requestSize, + &found); + + MemSet(fpPtr, 0, requestSize); /* For asserts checking we did not overflow. */ - fpEndPtr = fpPtr + (TotalProcs * (fpLockBitsSize + fpRelIdSize)); + fpEndPtr = fpPtr + requestSize; for (i = 0; i < TotalProcs; i++) { @@ -330,7 +377,9 @@ InitProcGlobal(void) PreparedXactProcs = &procs[MaxBackends + NUM_AUXILIARY_PROCS]; /* Create ProcStructLock spinlock, too */ - ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t)); + ProcStructLock = (slock_t *) ShmemInitStruct("ProcStructLock spinlock", + sizeof(slock_t), + &found); SpinLockInit(ProcStructLock); } |